Программирование. Принципы и практика использования C++ Исправленное издание, стр. 391
void f(){ char i = 0; char j = 0; char* p = &i; void* q = p; int* pp = q; /* небезопасно; разрешено в языке C, ошибка в языке C++ */ *pp = –1; /* перезаписываем память, начиная с адреса &i */В данном случае мы даже не уверены, какой фрагмент памяти будет перезаписан: переменная
jpf()ff()Обратите внимание на то, что (обратное) преобразование указателя типа
T*void*К сожалению, неявное преобразование
void*T*27.3.6. Перечисление
В языке C можно присваивать целое число перечислению без приведения
intenumenum color { red, blue, green };int x = green; /* OK в языках C и C++ */enum color col = 7; /* OK в языке C; ошибка в языке C++ */Одним из следствий этого факта является то, что в программах на языке С мы можем применять операции инкрементации (
++––enum color x = blue;++x; /* переменная x становится равной значению green; ошибка в языке C++ */++x; /* переменная x становится равной 3; ошибка в языке C++ */Выход за пределы перечисления может входить в наши планы, а может быть неожиданным.
Обратите внимание на то, что, подобно дескрипторам структур, имена перечислений пребывают в своем собственном пространстве имен, поэтому каждый раз при указании имени перечисления перед ним следует ставить ключевое слово
enumcolor c2 = blue; /* ошибка в языке C: переменная color не находится в пределах области видимости; OK в языке C++ */enum color c3 = red; /* OK */27.3.7. Пространства имен
В языке С нет пространств имен (в том смысле, как это принято в языке С++). Так что же можно сделать, чтобы избежать коллизий имен в больших программах, написанных на языке С? Как правило, для этого используются префиксы и суффиксы. Рассмотрим пример.
/* в bs.h: */typedef struct bs_string { /* ... */ } bs_string; /* строка Бьярне */typedef int bs_bool; /* булев тип Бьярне *//* in pete.h: */typedef char* pete_string; /* строка Пита */typedef char pete_bool; /* булев тип Пита */Этот прием настолько широко используется, что использовать одно- и двухбуквенные префиксы обычно уже недостаточно.
27.4. Свободная память
В языке С нет операторов
newdelete<stdlib.h>void* malloc(size_t sz); /* выделить sz байтов */void free(void* p); /* освободить область памяти, на которую ссылается указатель p */void* calloc(size_t n, size_t sz); /* выделить n*sz байтов, инициализировав их нулями */void* realloc(void* p, size_t sz); /* вновь выделить sz байтов в памяти, на которую ссылается указатель p*/Тип
typedef size_t<stdlib.h>
malloc()void*struct Pair { const char* p; int val;};struct Pair p2 = {"apple",78};struct Pair* pp = (struct Pair*) malloc(sizeof(Pair)); /* выделить память */pp–>p = "pear"; /* инициализировать */pp–>val = 42;Теперь мы не можем написать инструкцию
*pp = {"pear", 42}; /* ошибка: не C и не C++98 */