Объявление целочисленного типа фиксированного размера typedef в стандарте C - PullRequest
4 голосов
/ 10 октября 2009

Существует ли надежный способ объявления typedef для целочисленных типов с фиксированной длиной 8, 16, 32 и 64-битной длины в стандарте ISO C?

Когда я говорю Стандарт ISO C, я имею в виду, что строго:

  • ISO C89 / C90, а не C99.
  • Заголовки не определены в стандарте ISO.
  • Никакие символы препроцессора не определены в стандарте ISO.
  • Нет допущений относительно размера шрифта, не указанных в стандарте ISO.
  • Нет фирменных символов поставщиков.

Я вижу другие вопросы, подобные этому, в StackOverflow, но пока нет ответов, которые не нарушали бы одно из вышеуказанных ограничений. Я не уверен, что это возможно без обращения к символам платформы.

Ответы [ 5 ]

8 голосов
/ 10 октября 2009

Да Вы можете.

Заголовочный файл limits.h должен быть частью C90. Затем я протестировал бы значения директив препроцессора SHRT_MAX, INT_MAX, LONG_MAX и LLONG_MAX и соответственно установил typedefs.

Пример:

#include <limits.h>

#if SHRT_MAX == 2147483647
typedef unsigned short int uint32_t;
#elif INT_MAX == 2147483647
typedef unsigned int uint32_t;
#elif LONG_MAX == 2147483647
typedef unsigned long uint32_t ;
#elif LLONG_MAX == 2147483647
typedef unsigned long long uint32_t;
#else
#error "Cannot find 32bit integer."
#endif
6 голосов
/ 10 октября 2009

Строго говоря, ISO 9899: 1999 заменил ISO 9899: 1990, поэтому является единственной действующей спецификацией языка C стандарта ISO.

Поскольку точные имена typedef ширины для целочисленных типов были введены в стандарт только в версии 1999 года, то, что вы хотите, невозможно при использовании только версии 1990 стандарта.

3 голосов
/ 10 октября 2009

Там нет ни одного. Однако существует надежный способ объявить отдельные целочисленные переменные размером до 32 бит, если вы готовы жить с некоторыми ограничениями. Просто используйте long битовые поля (последние гарантированно должны иметь ширину не менее 32 бит, и вы можете использовать столько битов в битовых полях, сколько уместилось бы в переменной, если бы был опущен декларатор битового поля). Итак:

struct {
   unsigned long foo : 32; 
} bar;

Очевидно, что вы получаете все ограничения, которые идут с этим, такие как невозможность иметь указатели на такие переменные. Единственное, что действительно покупает вас, - это гарантированный перенос по указанной границе при переполнении / недостаточном заполнении, и даже в этом случае только для неподписанных типов, поскольку переполнение для знакового не определено.

Кроме этого, нет никакого портативного способа сделать это в чистом C90. Помимо прочего, для реализации C90, соответствующей требованиям, даже не нужно иметь 8-битное целое число - например, было бы вполне законно иметь платформу, в которой sizeof(char) == sizeof(short) == sizeof(int) == 1 и CHAR_BIT == 16 (т.е. она имеет 16-битное машинное слово, и не может адресовать отдельные байты). Я слышал, что такие платформы действительно существуют на практике в виде некоторых DSP.

0 голосов
/ 14 апреля 2017

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

0 голосов
/ 10 октября 2009

Нет, вы не можете этого сделать.

Теперь, если вы хотите посчитать многоступенчатый процесс конфигурации, такой как Gnu configure, как решение, вы можете сделать это и придерживаться C89. И, безусловно, есть различные типы, которые вы можете использовать, - в C89, и это будет DTRT почти для каждой реализации, существующей сегодня, так что вы получите желаемые размеры и придерживаетесь чистого C89. Но ширина битов, в то время как вы хотите, в общем случае не будет определяться стандартом.

...