Выбрать главу

Стандарт языка С явно указывает, что размер памяти, которую занимают переменные стандартных типов данных, зависит от аппаратной реализации[93], при этом также определяется минимально возможный размер типа. Неопределенность размеров стандартных типов языка С для различных аппаратных платформ имеет свои положительные и отрицательные стороны. К плюсам можно отнести то, что для стандартных типов языка С можно пользоваться преимуществами, связанными с размером машинного слова, а также отсутствие необходимости явного указания размера. Для ОС Linux размер типа long гарантированно равен размеру машинного слова. Это не совсем соответствует стандарту ANSI С, однако является стандартной практикой в ОС Linux. Как недостаток можно отметить, что при разработке кода нельзя рассчитывать на то, что данные определенного типа занимают в памяти определенный размер. Более того, нельзя гарантировать, что переменные типа int занимают столько же памяти, сколько и переменные типа long[94].

Ситуация еще более запутывается тем, что одни и те же типы данных в пространстве пользователя и в пространстве ядра не обязательно должны соответствовать друг другу. Аппаратная платформа sparc64 предоставляет 32-разрядное пространство пользователя, а поэтому указатели, типы int и long имеют размер 32 бит. Однако в пространстве ядра для аппаратной платформы размер типа int равен 32 бит, а размер указателей и типа long равен 64 бит. Тем не менее такая ситуация не является обычной.

Всегда необходимо помнить о следующем.

• Как и требует стандарт языка С, размер типа char всегда равен 8 бит (1 байт),

• Нет никакой гарантии, что размер типа int для всех поддерживаемых аппаратных платформ будет равен 32 бит, хотя сейчас для всех платформ он равен именно этому числу.

• То же касается и типа short, который для всех поддерживаемых аппаратных платформ сейчас равен 16 бит.

• Никогда нельзя надеяться, что тип long или указатель имеет некоторый заданный размер. Этот размер для поддерживаемых аппаратных платформ может быть равен 32, или 64 бит.

• Так как размер типа long разный для различных аппаратных платформ, никогда нельзя предполагать, что sizeof(int) == sizeof(long).

• Точно так же нельзя предполагать, что размер типа int и размер указателя совпадают.

Скрытые типы данных

Скрытые (opaque) типы данных — это те типы, для которых не раскрывается их внутренняя структура, или формат. Они похожи на черный ящик, насколько это можно реализовать в языке программирования С. В этом языке программирования нет какой-либо особенной поддержки для этих типов. Вместо этого, разработчики определяют новый тип данных через оператор typedef, называют его скрытым и надеются на то, что никто не будет преобразовывать этот тип в стандартный тип данных языка С. Любые использования данных этих типов возможны только через специальные интерфейсы, которые также создаются разработчиком. Примером может быть тип данных pid_t, в котором хранится информация об идентификаторе процесса. Размер этого типа данных не раскрывается, хотя каждый может смошенничать, использовать размер по максимуму и работать с этим типом, как с типом int. Если нигде явно не используется размер скрытого типа данных, то размер этого типа может быть изменен, и это не вызовет никаких проблем. На самом деле так уже однажды случилось: в старых Unix-подобных операционных системах тип pid_t был определен как short.

Еще один пример скрытого типа данных — это тип atomic_t. Как уже обсуждалось в главе 9, "Средства синхронизации в ядре", этот тип содержит данные целочисленного типа, с которыми можно выполнять атомарные операции. Хотя этот тип и соответствует типу int, использование скрытого типа данных позволяет гарантировать, что данные этого типа будут использоваться только в специальных функциях, которые выполняют атомарные операции. Скрытые типы позволяют скрыть размер типа данных, который не всегда равен полным 32 разрядам, как в случае платформы SPARC.

вернуться

93

За исключением размера типа char, который всегда равен 8 бит.

вернуться

94

На самом деле, для 64-разрядных аппаратных платформ, которые поддерживаются ОС Linux, размеры типов int и long не совпадают. Размер типа int равен 32 бит, а размер типа long — 64 бит. Для хорошо знакомых 32-разрядных аппаратных платформ оба типа данных имеют размер 32 бит.