C: Почему size_t не является ключевым словом C? - PullRequest
26 голосов
/ 11 апреля 2009

sizeof - это ключевое слово C . Возвращает размер в типе с именем size_t. Тем не менее, size_t является не ключевым словом, но определено в основном в stddef.h и, вероятно, также в других стандартных заголовочных файлах языка Си.

Рассмотрим сценарий, в котором вы хотите создать программу на C, в которую не входит никаких стандартных заголовков или библиотек на языке C. (Как, например, если вы создаете ядро ​​ОС.) Теперь в таком коде можно использовать sizeof (это ключевое слово C, поэтому оно является частью языка ), но возвращаемый тип (size_t) недоступен!

Не означает ли это какую-то проблему в спецификации стандарта C? Вы можете это уточнить?

Ответы [ 10 ]

45 голосов
/ 11 апреля 2009

Он не возвращает буквально значение типа size_t, поскольку size_t не является конкретным типом сам по себе, а скорее typedef для неопределенного встроенного типа. Идентификаторы Typedef (например, size_t) полностью эквивалентны соответствующим базовым типам (и преобразуются в них во время компиляции). Если size_t определен как unsigned int на вашей платформе, то sizeof возвращает unsigned int, когда он компилируется в вашей системе. size_t - это просто удобный способ поддержания переносимости, его нужно включать в stddef.h только в том случае, если вы используете его явно по имени.

14 голосов
/ 11 апреля 2009

sizeof - это ключевое слово, потому что, несмотря на его название и использование, оно является оператором подобно + или = или <, а не функцией подобно printf() или atoi() или fgets(). Многие люди забывают (или просто не знают), что sizeof на самом деле является оператором и всегда разрешается во время компиляции, а не во время выполнения.

Для языка C не требуется size_t, чтобы быть пригодным для использования и согласованным языком. Это только часть стандартной библиотеки. Язык Си нуждается во всех операторах. Если бы вместо + C использовал ключевое слово plus для добавления чисел, вы бы сделали его оператором.

Кроме того, я делаю полу-неявное преобразование от size_t с до unsigned int с (и регулярно int с, но Керниган и Ричи когда-нибудь меня за это поразят) все время. Вы можете присвоить тип возвращаемого значения sizeof для int, если хотите, но в своей работе я обычно просто передаю его прямо в malloc() или что-то в этом роде.

8 голосов
/ 11 апреля 2009

Некоторые заголовки из стандарта C определены для автономной среды, то есть пригодной для использования, например. в ядре операционной системы. Они не определяют никаких функций, просто определяют и вводят определения.

Это float.h, iso646.h, limit.h, stdarg.h, stdbool.h, stddef.h и stdint.h.

При работе в операционной системе неплохо начинать с этих заголовков. Наличие их делает многие вещи проще в вашем ядре. Особенно пригодится stdint.h (uint32_t и др.).

7 голосов
/ 12 апреля 2009

Не означает ли это какую-то проблему в спецификации стандарта C?

Посмотрите на разницу между размещенной реализацией C и отдельно стоящей реализацией C. Для обеспечения заголовков требуется автономная реализация (C99):

  • <float.h>
  • <iso646.h>
  • <limits.h>
  • <stdarg.h>
  • <stdbool.h>
  • <stddef.h>
  • <stdint.h>

Эти заголовки вообще не определяют никаких функций. Они определяют части языка, которые в некоторой степени зависят от компилятора (например, макрос offsetof в <stddef.h>, а также макросы и переменные списка переменных в <stdarg.h>), но они могут обрабатываться без фактического встраивания язык как полные ключевые слова.

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

4 голосов
/ 11 апреля 2009

Я думаю, что основные причины того, что size_t не является ключевым словом:

  • нет веской причины для этого. Разработчики языков C и C ++ всегда предпочитали, чтобы возможности языка были реализованы в библиотеке, если это возможно и целесообразно
  • добавление ключевых слов к языку может создать проблемы для существующей части устаревшего кода. Это еще одна причина, по которой они обычно не добавляют новые ключевые слова.

Например, при обсуждении следующего крупного пересмотра стандарта C ++ Страуструп сказал следующее: :

Улучшения в C ++ 0x должны быть сделаны таким образом, чтобы полученный язык был легче выучить и использовать. Среди практических правил для комитета:

...

  • Предпочитать стандартные библиотечные средства языковым расширениям

...

3 голосов
/ 11 апреля 2009

Нет причин не включать stddef.h, даже если вы работаете с ядром - он определяет размеры шрифтов для вашего конкретного компилятора, которые понадобятся любому коду.

Обратите внимание, что почти все компиляторы Си являются самоскомпилированными. Поэтому фактический код компилятора для оператора sizeof будет использовать size_t и ссылаться на тот же файл stddef.h, что и код пользователя.

2 голосов
/ 11 апреля 2009

С MSDN :

Когда применяется оператор sizeof для объекта типа char это дает 1

Даже если у вас нет / включен stddef.h и вы не знаете о size_t, с помощью sizeof вы можете получить размер объектов относительно char.

2 голосов
/ 11 апреля 2009

size_t на самом деле является типом - часто без знака int. Sizeof это оператор, который дает размер типа. Тип, возвращаемый sizeof, на самом деле зависит от реализации, а не от языка Си. Это просто целое число.

Edit: Чтобы быть очень понятным, вам не нужен тип size_t для использования sizeof. Я думаю, что вы ищете ответ: да, это противоречиво. Тем не менее, это не имеет значения. Вы по-прежнему можете практически правильно использовать sizeof, не имея определения size_t из файла заголовка.

1 голос
/ 11 апреля 2009

Простая причина в том, что это не фундаментальный тип. Если вы посмотрите стандарт C, вы обнаружите, что основные типы включают int, char и т. Д., Но не size_t. Почему так? Как уже указывали другие, size_t является специфичным для реализации типом (т. Е. Типом, способным содержать размер в количестве «байтов C» любого объекта).

С другой стороны, sizeof является (унарным) оператором. Все операторы являются ключевыми словами.

1 голос
/ 11 апреля 2009

size_t не является ключевым словом по необходимости. Различные архитектуры часто имеют разные размеры для целочисленных типов. Например, 64-битная машина может иметь unsigned long long как size_t , если они не решили сделать int 64-битным типом данных.

Если вы сделаете размер встроенного типа для компилятора, то это отнимет мощность для кросс-компиляции.

Кроме того, sizeof больше похож на магический макрос времени компиляции (например, шаблон c ++), который объясняет, почему это ключевое слово, а не определенный тип.

...