Керниган и Ритчи - Язык программирования Си (793773), страница 51
Текст из файла (страница 51)
Объявления с auto и register одновременноявляются определениями и резервируют память. Спецификатор register эквивалентен auto, но содержитподсказку, сообщающую, что в программе объявленные им объекты используются интенсивно. На регистрахможет быть размещено лишь небольшое число объектов, причем определенного типа; указанныеограничения зависят от реализации. В любом случае к register-объекту нельзя применять (явно илинеявно) унарный оператор &.Новым является правило, согласно которому вычислять адрес объекта класса register нельзя, акласса auto можно.Спецификатор static дает объявляемым объектам класс статической памяти, он может использоваться ивнутри, и вне функций.
Внутри функции этот спецификатор вызывает выделение памяти и служитопределением; его роль вне функций будет объяснена в А11.2.Объявление со спецификатором extern, используемое внутри функции, объявляет, что для объявляемогообъекта где-то выделена память; о ее роли вне функций будет сказано в А11.2.Спецификатор typedef не резервирует никакой памяти и назван спецификатором класса памяти изсоображений стандартности синтаксиса; речь об этом спецификаторе пойдет в А8.9.Объявление может содержать не более одного спецификатора класса памяти.
Если он в объявленииотсутствует, то действуют следующие правила: считается, что объекты, объявляемые внутри функций, имеюткласс auto; функции, объявляемые внутри функций, — класс extern; объекты и функции, объявляемые внефункций, — статические и имеют внешние связи (см. А10, А11).А 8.2. Спецификаторы типаСпецификаторы типа определяются следующим образом:спецификатор-типа:voidcharshortintlongfloatdoublesignedunsignedструктуры-или-объединения-спецификаторспецификатор-перечисленияtypedef-имяВместе с int допускается использование еще какого-то одного слова — long или short; причем сочетаниеlong int имеет тот же смысл, что и просто long; аналогично short int — то же самое, что и short.Слово long может употребляться вместе с double.
С int и другими его модификациями (short, long илиchar) разрешается употреблять одно из слов signed или unsigned. Любое из последних можетиспользоваться самостоятельно, в этом случае подразумевается int.Спецификатор signed бывает полезен, когда требуется обеспечить, чтобы объекты типа char имели знак;его можно применять и к другим целочисленным типам, но в этих случаях он избыточен.За исключением описанных выше случаев объявление не может содержать более одного спецификаторатипа.
Если в объявлении нет ни одного спецификатора типа, то имеется в виду тип int.Для указания особых свойств объявляемых объектов предназначаются квалификаторы:квалификатор-типа:constvolatileКвалификаторы типа могут употребляться с любым спецификатором типа. Разрешается инициализироватьconst-объект, однако присваивать ему что-либо в дальнейшем запрещается. Смысл квалификатораvolatile зависит от реализации.Средства const и volatile (изменчивый) введены стандартом ANSI.
Квалификатор constприменяется, чтобы разместить объекты в памяти, открытой только на чтение (ПЗУ), или чтобыспособствовать возможной оптимизации. Назначение квалификатора volatile — подавитьоптимизацию, которая без этого указания могла бы быть проведена. Например, в машинах, где адресарегистров ввода-вывода отображены на адресное пространство памяти, указатель на регистрнекоторого устройства мог бы быть объявлен как volatile, чтобы запретить компилятору экономитьочевидно избыточную ссылку через указатель. Компилятор может игнорировать указанныеквалификаторы, однако обязан сигнализировать о явных попытках изменить значение constобъектов.А 8.3.
Объявления структур и объединенийСтруктура — это объект, состоящий из последовательности именованных элементов различных типов.Объединение — объект, который в каждый момент времени содержит один из нескольких элементовразличных типов. Объявления структур и объединений имеют один и тот же вид.структуры-или-объединения-спецификатор:структуры-или-объединения идентификаторнеоб { список-объявлений-структуры }структуры-или-объединения идентификаторструктура-или-объединение:structunionСписок-объявлений-структуры является последовательностью объявлений элементов структуры илиобъединения:список-объявлений-структуры:объявление-структурысписок-объявлений-структуры объявление-структурыобъявление-структуры:список-спецификаторов-квалификаторов список-структуры-объявителей ;список-спецификаторов-квалификаторов:спецификатор-типа список-спецификаторов-квалификаторовнеобквалификатор-типа список-спецификаторов-квалификаторовнеобсписок-структуры-объявителей:структуры-объявительсписок-структуры-объявителей , структуры-объявительОбычно объявление-структуры является просто объявлением для элементов структуры или объединения.Элементы структуры, в свою очередь, могут состоять из заданного числа разрядов (битов).
Такой элементназывается битовым полем или просто полем. Его размер отделяется от имени поля двоеточием:структуры-объявитель:объявительобъявительнеоб : константное-выражениеСпецификатор типа, имеющий видструктуры-или-объединения идентификатор {список-объявлений-структуры }объявляет идентификатор тегом структуры или объединения, специфицированных списком. Последующееобъявление в той же или внутренней области видимости может обращаться к тому же типу, используя вспецификаторе тег без списка:структуры-или-объединения идентификаторЕсли спецификатор с тегом, но без списка появляется там, где тег не объявлен, специфицируетсянезавершенный тип.
Объекты с незавершенным типом структуры или объединения могут упоминаться вконтексте, где не требуется знать их размер — например в объявлениях (но не определениях) для описанияуказателя или создания typedef, но не в иных случаях. Тип становится завершенным при появлениипоследующего спецификатора с этим тегом, содержащего список объявлений. Даже в спецификаторах сосписком объявляемый тип структуры или объединения является незавершенным внутри списка и становитсязавершенным только после появления символа }, заканчивающего спецификатор.Структура не может содержать элементов незавершенного типа.
Следовательно, невозможно объявитьструктуру или объединение, которые содержат сами себя. Однако, кроме придания имени типу структуры илиобъединения, тег позволяет определять структуры, обращающиеся сами к себе; структура или объединениемогут содержать указатели на самих себя, поскольку указатели на незавершенные типы объявлять можно.Особое правило применяется к объявлениям видаструктуры-или-объединения идентификатор ;которые объявляют структуру или объединение, но не имеют списка объявления и объявителя. Даже еслиидентификатор имеет тег структуры или объединения во внешней области видимости (А11.1), это объявлениеделает идентификатор тегом новой структуры или объединения незавершенного типа во внутренней областивидимости.Это невразумительное правило — новое в ANSI. Оно предназначено для взаимно рекурсивныхструктур, объявленных во внутренней области видимости, но теги которых могут быть уже объявленыво внешней области видимости.Спецификатор структуры или объединения со списком, но без тега создает уникальный тип, к которомуможно обращаться непосредственно только в объявлении, частью которого он является.Имена элементов и тегов не конфликтуют друг с другом или обычными переменными.
Имя элемента неможет появляться дважды в одной и той же структуре или объединении, но тот же элемент можноиспользовать в разных структурах или объединениях.В первой редакции этой книги имена элементов структуры и объединения не связывались со своимиродителями. Однако в компиляторах эта связь стала обычной задолго до появления стандарта ANSI.Элемент структуры или объединения, не являющийся полем, может иметь любой тип объекта. Поле (котороене имеет объявителя и, следовательно, может быть безымянным) имеет тип int, unsigned int илиsigned int и интерпретируется как объект целочисленного типа указанной в битах длины. Считается липоле int знаковым или беззнаковым, зависит от реализации.
Соседний элемент-поле упаковывается вячейки памяти в зависимости от реализации в зависящем от реализации направлении. Когда следующее заполем другое поле не влезает в частично заполненную ячейку памяти, оно может оказаться разделенныммежду двумя ячейками, или ячейка может быть забита балластом. Безымянное поле нулевой шириныобязательно приводит к такой забивке, так что следующее поле начнется с края следующей ячейки памяти.Стандарт ANSI делает поля еще более зависимыми от реализации, чем в первой редакции книги.Чтобы хранить битовые поля в "зависящем от реализации" виде без квалификации, желательнопрочитать правила языка. Структуры с битовыми полями могут служить переносимым способом дляпопытки уменьшить размеры памяти под структуру (вероятно, ценой увеличения кода программы ивремени на доступ к полям) или непереносимым способом для описания распределения памяти набитовом уровне. Во втором случае необходимо понимать правила местной реализации.Элементы структуры имеют возрастающие по мере объявления элементов адреса.
Элементы структуры, неявляющиеся полями, выравниваются по границам адресов в зависимости от своего типа; таким образом, вструктуре могут быть безымянные дыры. Если указатель на структуру приводится к типу указателя на еепервый элемент, результат указывает на первый элемент.Объединение можно представить себе как структуру, все элементы которой начинаются со смещением 0 иразмеры которой достаточны для хранения любого из элементов. В любой момент времени в объединениихранится не больше одного элемента. Если указатель на объединение приводится к типу указателя на один изэлементов, результат указывает на этот элемент.Вот простой пример объявления структуры:struct tnode {char tword[20];int count;struct tnode *left;struct tnode *right;};Эта структура содержит массив из 20 символов, число типа int и два указателя на подобную структуру.















