Правила инициализации переменных
Инициализация переменных определяется конструкцией вида:
Переменная = <инициализатор>;
Основные правила:
1. Если описание переменной начинается со служебного слова EXTERN, то явная инициализация не допустима.
2. Переменные, описанные на внешнем уровне можно явно инициализировать. При неявной инициализации они получают нулевые значения.
3. Cтатическим переменным можно присваивать значения константного выражения. По умолчанию они инициализируются нулем.
4. Автоматические и регистровые переменные инициализируются при
каждом входе в блок, где они описаны. По умолчанию их значения не определены.
5. Данные составного типа (массивы, структуры) можно инициализировать на внешнем или на внутреннем уровне. В последнем случае они инициализируются при входе в блок. При выходе из блока значения автоматических и регистровых переменных теряются.
Инициализация переменных составного типа.
Cинтаксис:
Имя переменной ={<cписок инициализаторов>};
Основные правила:
1.Значения константных выражений из списка инициализаторов присваиваются элементам объекта в порядке их следования.
2.Если в списке инициализаторов меньше элементов, чем в объекте составного типа, то оставшиеся элементы неявно инициализируются 0, а если больше, то регистрируется ошибка.
Пример:
int array [3] [3]=
{
{1,1,1}, //инициализация первой строки
{2,2,2}, //инициализация второй строки
{3,3,3}, // инициализация третьей строки
}
Внутренние скобки играют важную роль, особенно в тех случаях, когда имеются сложные описания, например, массивы структур. Здесь нужно быть особенно внимательным.
Пример неверной инициализации:
struct
{ int a1,a2,a3,;} st [2] [3]=
{
{1,2,3}, {4,5,6}, {7,8,9},
{10,11,12}, {13,14,15}, {16,17,18}
};
Примеры строковых инициализаторов
char str[] =”abc”;
char str[3] =”abcd” //неверно
char *str =”abcd”;
Указатель str будет инициализирован адресом массива типа char, содержащего символы ‘a’,’b’,’c’,’d’,’\0’.
Модели памяти
Архитектура микропроцессора предусматривает разбиение оперативной памяти на физические сегменты. Размер каждого сегмента равен 64 Кбайт (К=1024). Вычисление физического адреса осуществляется путем сложения 16 - разрядного адреса сегмента, сдвинутого на 4 разряда, с адресом смещения в соответствии со следующей схемой:
15 0
. . . . . . . . Базовый
сегмент
15 0
Смещение . . . . . . . . . . . . . . .
19 0
20 – разрядный физический адрес
Адрес сегмента адресует память с «точностью» до 16 байт (или с точностью до параграфа); смещение адресует память с точностью до байта в пределах 64 Кбайт, размещение в памяти которых определяется начальным адресом сегмента.
Распределение памяти для программы на языке Си осуществляется следующим образом:
1. По умолчанию программе выделяется суммарный объем памяти, равный 128 Кбайт.
- 64 Кбайт для кода программы;
- 64 Кбайт для статистических данных и стека.
Такая модель памяти называется малой (small). В малой модели для доступа к объектам программы (коду или данным) используются указатели типа near – ближние указатели.
2. Если размер кода программы превышает 64 Кбайта, а для размещения стека и данных достаточно 64 Кбайта, то применяется средняя модель памяти (medium) . В такой модели для функций используются дальние указатели far, а для данных near.
3. Если размер программного кода не велик, а данные требуют больше, чем 64 Кбайт, то используется компактная (compact) модель памяти.
В такой модели доступ к объектам программы осуществляется с помощью указателей типа far, а в максимальной модели с помощью указателей типа huge.
4. Если как для данных, так и для кода требуется больше одного сегмента (>64 Кбайт), то применяется либо большая (large) модель, либо огромная(huge) модель.
Разница между указателями far и huge заключается в том, что в адресной арифметике при вычислении far указателей на данные используется 16- битное смещение. Это ограничивает размер отдельного элемента данных значением 64 Кбайт. Указанное ограничение снято в огромной модели памяти. Адреса huge позволяют использовать массивы, размер которых превышает 64 Кбайт. В адресной арифметике используются все 32 разряда, а тип результата unsigned long.
Работая в любой модели памяти, программист имеет возможность ее модификации, применяя явно модификаторы near, far и huge.
Так, например, если за модификатором near, far или huge следует идентификатор, то соответствующий программный объект будет размещен либо в стандартном сегменте (для near), либо в другом сегменте (для far и huge).
Объявление
char far ch;
означает, что адрес ch будет иметь тип far.