На этом шаге мы рассмотрим особенности различных категорий памяти.
Каждая объявленная переменная относится к той или иной категории памяти. Ранее мы видели, что переменные бывают глобальные или локальные. Принадлежность к одной из этих категорий определяет время жизни переменной. Действительно, локальные (или как их еще называют, автоматические) переменные "живут", пока они находятся в теле функции, оператора или блока. По выходе их этих конструкций переменная уничтожается: ее память становится доступной к перераспределению для других переменных.
Глобальные (их еще называют статическими) переменные "живут", пока работает ваша программа. Все функции относятся к глобальным переменным. Язык С, кроме того, имеет ряд спецификаторов категорий памяти, которые явно указывают на это компилятору. Мы уже встречались с некоторыми из них: это спецификаторы extern и static. Первый применяется при определении так называемых внешних переменных (они определяются вне вашей программы, например, в подключаемом к ней h-фале). Внешние переменные тоже являются глобальными. Второй спецификатор позволяет "глобализовать" локальную переменную: при выходе из локализующей ее конструкции такая переменная не теряет своего значения, как не теряет его она и при входе в свою конструкцию. К другим спецификаторам категории памяти относятся спецификаторы: auto, register, typedef.
В объявлении переменной вы можете использовать только один спецификатор категории памяти. Если категория памяти в объявлении переменной не указана, то категория принимается равной auto и объявление переменной внутри блока, функции или оператора создает автоматические переменные. Переменные, объявленные с категорией register, будут также отнесены к автоматическим (т. е. локальным). Переменные, объявленные с категориями static или extern, будут отнесены к глобальным.
Если переменной при ее объявлении присваивается категория register, то это означает, что при промежуточных операциях с такой переменной ее содержимое станет размещаться не в оперативной памяти, а в регистрах компьютера, что значительно увеличивает скорость работы с такой переменной.
Спецификатор typedef фактически вводит синоним типа, давая возможное программисту вводить типы данных с подходящими ему наименованиям чтобы улучшить читаемость программы. Вот структура его спецификации:
typedef [заменяемые типы: void, char, short, int, long, float, double, signed, unsigned, struct, enum] новое имя;
Например:
typedef char Flag;
Здесь тип char заменен синонимом Flag. Теперь в вашей программе можно вместо char везде писать Flag. Например, Flag b='b';. Если же вы используете имя переменной, совпадающее с синонимом, определенным typedef, такая переменная, как обычно, должна иметь тип данного. Например:
int Flag = 12;
Другой пример:
typedef struct club { char name[30]; int size, year; } GROUP;
Здесь вся структура заменена синонимом GROUP. Теперь переменные структуры club можно объявлять переменными типа GROUP:
GROUP a, b, *c; a.size = 123; b.year = 2007; c= new GROUP; //выделили память под структуру (инициализировали указатель) c->name[0] = 'a'; c->name[l] = 'b'; //Или: enum days {sun, mon, tues, wed, thur, fri, sat}; //ввели тип typedef days d; d dd; dd=sat; //Или: typedef char* cc; //замена указателя cc str; str="123"; int i = atoi(str);
Со следующего шага мы начнем рассматривать классы в C++.