Читаем Программирование. Принципы и практика использования C++ Исправленное издание полностью

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++ */

Выход за пределы перечисления может входить в наши планы, а может быть неожиданным.

Обратите внимание на то, что, подобно дескрипторам структур, имена перечислений пребывают в своем собственном пространстве имен, поэтому каждый раз при указании имени перечисления перед ним следует ставить ключевое слово enum.

color c2 = blue;     /* ошибка в языке C: переменная color не находится

                        в пределах области видимости; OK в языке C++ */

enum color c3 = red; /* OK */

<p id="AutBody_Root549"><strong>27.3.7. Пространства имен</strong></p>

В языке С нет пространств имен (в том смысле, как это принято в языке С++). Так что же можно сделать, чтобы избежать коллизий имен в больших программах, написанных на языке С? Как правило, для этого используются префиксы и суффиксы. Рассмотрим пример.

/* в bs.h: */

typedef struct bs_string { /* ... */ } bs_string; /* строка

                                                     Бьярне */

typedef int bs_bool; /* булев тип Бьярне */

/* in pete.h: */

typedef char* pete_string; /* строка Пита */

typedef char pete_bool;    /* булев тип Пита */

Этот прием настолько широко используется, что использовать одно- и двухбуквенные префиксы обычно уже недостаточно.

<p id="AutBody_Root550"><strong>27.4. Свободная память</strong></p>

 В языке С нет операторов new и delete, работающих с объектами. Для использования свободной памяти в нем используются функции, работающие с памятью. Наиболее важные функции определены в стандартном заголовочном файле общих утилит .

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 — это тип без знака, также определенный в заголовочном файле .

  Почему функция 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 */

ни в программе на языке C, ни в программе на языке C++. Однако в языке С++ мы могли бы определить конструктор для структуры Pair и написать инструкцию Pair* pp = new Pair("pear", 42);

В языке C (но не в языке C++; см. раздел 27.3.4) перед вызовом функции malloc можно не указывать приведение типа, но мы не рекомендуем это делать.

int* p = malloc(sizeof(int)*n); /* избегайте этого */

Игнорирование приведения довольно часто встречается в программах, потому что это экономит время и позволяет выявить редкую ошибку, когда программист забывает включить в текст программы заголовочный файл перед использованием функции malloc. Однако при этом исчезает и визуальный маркер, свидетельствующий о том, что размер памяти подсчитан неправильно.

p = malloc(sizeof(char)*m); /* вероятно, ошибка — нет места для m целых */

Перейти на страницу:

Похожие книги

97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT