Язык С

       

Смысл описателей


Каждый описатель рассматривается как утверждение того, что когда конструкция той же самой формы, что и описатель, появляется в выражении, то она выдает объект указанного типа и указанного класса памяти. Каждый описатель содержит ровно один идентификатор; это именно тот идентификатор, который и описывается. Если в качестве описателя появляется просто идентифика- тор, то он имеет тип, указываемый в специфицирующем заголов- ке описания. Описатель в круглых скобках идентичен описателю без круглых скобок, но круглые скобки могут изменять связи в составных описателях. Примеры смотри ниже. Представим себе описание

T DI

где T - спецификатор типа (подобный INT и т.д.), а DI - опи- сатель. Предположим, что это описание приводит к тому, что соответствующий идентификатор имеет тип "...T", где "..." пусто, если DI просто отдельный идентификатор (так что тип X в "INT X" просто INT). Тогда , если DI имеет форму

*D

то содержащийся идентификатор будет иметь тип "... Указатель на T".

Если DI имеет форму

D()

то содержащийся идентификатор имеет тип "... Функция, возв- ращающая T". Если DI имеет форму

D[константное-выражение]

или

D[ ]

то содержащийся идентификатор имеет тип "...массив T". В первом случае константным выражением является выражение, значение которого можно определить во время компиляции и ко- торое имеет тип INT. (Точное определение константного выра- жения дано в п. 23). Когда несколько спецификаций вида "мас- сив из" оказываются примыкающими, то создается многомерный массив; константное выражение, задающее границы массивов, может отсутствовать только у первого члена этой последова- тельности. Такое опускание полезно, когда массив является внешним и его фактическое определение, которое выделяет па- мять, приводится в другом месте. Первое константное выраже- ние может быть опущено также тогда, когда за описателем сле- дует инициализация. В этом случае размер определяется по числу приведенных инициализируемых элементов. Массив может быть образован из элементов одного из ос- новных типов, из указателей, из структур или объединений или из других массивов (чтобы образовать многомерный массив). Не все возможности, которые разрешены с точки зрения указанного выше синтаксиса, фактически допустимы. Имеются следующие ограничения: функции не могут возвращать массивы, структуры, объединения или функции, хотя они могут возвра- щать указатели на такие вещи; не существует массивов функ- ций, хотя могут быть массивы указателей на функции. Анало- гично, структуры или объединения не могут содержать функцию, но они могут содержать указатель на функцию. В качестве примера рассмотрим описание


INT I, *IP, F(), *FIP(), (*PFI)();

в котором описывается целое I, указатель IP на целое, функ- ция F, возвращающая целое, функция FIP, возвращающая указа- тель на целое, и указатель PFI на функцию, которая возвраща- ет целое. Особенно полезно сравнить два последних описателя. Связь в *FIP() можно представить в виде *(FIP()), так что описанием предполагается, а такой же конструкцией в выраже- нии требуется обращение к функции FIP и последующее исполь- зование косвенной адресации для выдачи с помощью полученного результата (указателя) целого. В описателе (*PFI)() дополни-

тельные скобки необходимы, поскольку они точно так же, как и в выражении, указывают, что косвенная адресация через указа- тель на функцию выдает функцию, которая затем вызывается; эта вызванная функция возвращает целое. В качестве другого примера приведем описание

FLOAT FA[17], *AFP[17];

в котором описывается массив чисел типа FLOAT и массив ука- зателей на числа типа FLOAT. Наконец,

STATIC INT X3D[3][5][7];

описывает статический трехмерный массив целых размером 3*5*7. более подробно, X3D является массивом из трех элемен- тов; каждый элемент является массивом пяти массивов; каждый последний массив является массивом из семи целых. Каждое из выражений X3D, X3D[I], X3D[I][J] и X3D[I][J][K] может разум- ным образом появляться в выражениях. Первые три имеют тип "массив", последнее имеет тип INT.




    Содержание раздела