Спецификаторы типа
Ниже перечисляются спецификаторы типа. спецификатор _ типа: char short int long unsigned float double спецификатор _ структуры _ или _ объединения спецификатор _ перечисления определяющее _ тип _ имя Слова long, short и unsigned можно рассматривать как прила-гательные; допустимы следующие комбинации: short int long int unsigned int long float Последняя комбинация означает то же, что и double. В осталь-ном описание может содержать не более одного спецификаторатипа. Если описание не содержит спецификатора типа, то счи-тается, что он имеет значение int. Спецификаторы структур и объединений обсуждаются в п.0.5, спецификация перечислимого типа - в п.0.6; описания сопределяющими тип именами typedef обсуждаются в п. 0.9. -23-Описатели
Входящий в описание список описателей представляетсобой последовательность разделенных запятыми описателей,каждый из которых может иметь инициализатор. список _ описателей: инициализируемый _ описатель инициализируемый _ описатель, спи - сок _ описателей инициализируемый _ описатель: описатель инициализатор необ Инициализаторы описываются в п.0.6. Спецификаторы и описанияуказывают тип и класс памяти объектов, на которые ссылаютсяописатели. Описатели имеют следующий синтаксис: описатель: идентификатор (описатель) * описатель описатель () описатель [ константное - выражение ] необ Группирование такое же, как и в выражениях.Смысл описателей
Каждый описатель рассматривается как утверждение того,что когда конструкция той же самой формы, что и описатель,появляется в выражении, то она выдает объект указанного типаи указанного класса памяти. Каждый описатель содержит ровноодин идентификатор; это именно тот идентификатор, который иописывается. Если в качестве описателя появляется просто идентифика-тор, то он имеет тип, указываемый в специфицирующем заго-ловке описания. Описатель в круглых скобках идентичен описателю безкруглых скобок, но круглые скобки могут изменять связи всоставных описателях. Примеры смотри ниже. Представим себе описание t di где t - спецификатор типа (подобный int и т.д.), а di - опи-сатель. Предположим, что это описание приводит к тому, чтосоответствующий идентификатор имеет тип... t, где "..."пусто, если di просто отдельный идентификатор (так что тип х -24- в int х просто int). Тогда, если di имеет форму *d то содержащийся идентификатор будет иметь тип... указательна t. Если di имеет форму d () то содержащийся идентификатор имеет тип... функция, возвра-щающая t. Если di имеет форму d [ константное _ выражение ] или d [ ] то содержащийся идентификатор имеет тип... массив t. В пер-вом случае константным выражением является выражение, значе-ние которого можно определить во время компиляции и котороеимеет тип int. (точное определение константного выражениядано ниже). Когда несколько спецификаций вида "массив из"оказываются примыкающими, то создается многомерный массив;константное выражение, задающее границы массивов, можетотсутствовать только у первого члена этой последователь-ности. Такое опускание полезно, когда массив является внеш-ним или формальным и его фактическое определение, котороевыделяет память, приводится в другом месте. Первое констант-ное выражение может быть опущено также тогда, когда за опи-сателем следует инициализация. В этом случае размер опреде-ляется по числу приведенных инициализируемых элементов. Массив может быть образован из элементов одного изосновных типов, из указателей, из структур или объединенийили из других массивов (чтобы образовать многомерный мас-сив). Не все возможности, которые разрешены с точки зренияуказанного выше синтаксиса, фактически допустимы. Имеютсяследующие ограничения: функции не могут возвращать массивыили функции, хотя они могут возвращать указатели на такиевещи; не существует массивов функций, хотя могут быть мас-сивы указателей на функции. Аналогично, структуры или объе-динения не могут содержать функцию, но они могут содержатьуказатель на функцию. В качестве примера рассмотрим описание -25- int i, *ip, f (), *fip (), (*pfi)(); в котором описывается целое i, указатель ip на целое, функ-ция f, возвращающая целое, функция fip, возвращающая указа-тель на целое, и указатель pfi на функцию, которая возвра-щает целое. Особенно полезно сравнить два последних описа-теля. Связь в *fip () можно представить в виде *(fip ()), такчто описанием предполагается, что в выражении требуетсяобращение к функции fip и последующее использование косвен-ной адресации для выдачи с помощью полученного результата(указателя) целого. В описателе (*pfi)() дополнительныескобки необходимы, поскольку они точно так же, как и в выра-жении, указывают, что косвенная адресация через указательвыдает функцию, которая затем вызывается; эта вызваннаяфункция возвращает целое. В качестве другого примера приведем описание float fa [17], *afp [17]; в котором описывается массив чисел типа float и массив ука-зателей на числа типа float. Наконец, static int х3d [3][5][7]; описывает статический трехмерный массив целых размером3*5*7. Более подробно: х3d является массивом из трех элемен-тов; каждый элемент является массивом пяти массивов; каждыйпоследний массив является массивом из семи целых. Каждое извыражений х3d, х3d [ i ], х3d [ i ][ j ] и х3d [ i ][ j ][ k ] может разум-ным образом появляться в выражениях. Первые три имеют тип"массив", последнее имеет тип int.