Насколько я вижу, sizeof(int)
и sizeof(long int)
вместе с их беззнаковыми аналогами равны 4. Вам на самом деле нужно набрать long long int
, чтобы получить 64-разрядное целое число (или int64_t
),так что long int
кажется совершенно лишним.
Язык Си не определяет точную ширину стандартных целочисленных типов.Скорее, он определяет минимальный диапазон значений, которые каждое из них должно представлять.Это позволяет писать С естественным образом для целей с различной архитектурой.В частности, соответствующая реализация может обеспечить int
s всего 15 битами значения, тогда как long int
должно иметь не менее 31, а long long int
должно иметь не менее 63. Целочисленные типы со знаком также имеют знаковый бит,а беззнаковые аналоги - один дополнительный бит значения.(Любой из них может также иметь биты заполнения, хотя это редко.) Так что нет, long int
не лишний, по крайней мере, не в семантическом смысле.
В этой среде почему __UINT32_TYPE__
предопределенный макрос, определенный как long unsigned int
?
Во-первых, __UINT32_TYPE__
- это деталь реализации glibc.Таким образом, единственный разумный ответ на поставленный вопрос - «потому что unsigned long int
- это тип, выбранный для uint32_t
».Но я хочу, чтобы вы спросили, почему этот тип был выбран в первую очередь.Я не могу однозначно говорить о причинах решений разработчиков GCC / glibc здесь, но я думаю, что я бы сделал такой же выбор на их месте, где они пытаются поддерживать самые разные архитектуры.
Потому что long int
и unsigned long int
гарантированно имеют как минимум 31 и 32 значения битов соответственно (а int
и unsigned int
- нет), длинные версии являются естественным выбором для [u
] int32_t
на этих платформахгде они фактически соответствуют его требованиям ( в точности 32 бита, без дополнительных битов, а подписанная версия реализована как дополнение к двум).Длинные версии являются единственным правильным выбором для некоторых поддерживаемых архитектур, и они являются одним из приемлемых вариантов для большинства остальных.Выбирая длинные версии, glibc должен делать исключения только для подмножества 64-разрядных платформ и, возможно, для нескольких платформ с целочисленными типами странных чисел.
Нет никаких требований и никаких оправданий для любых ожиданий, чтоint
и unsigned int
будут типами, выбранными для int32_t
и uint32_t
, когда они удовлетворяют требованиям для этого, если только они не являются только доступными типами, которые удовлетворяют требованиям.
Есть ли способ заменить uint32_t
на unsigned int
вместо этого?
Не существует соответствующего способа для вашего кода C изменить определение uint32_t
, предоставленноереализация.Вы можете попробовать взломать реализацию C, чтобы внести изменения, или вы можете выбрать совершенно другую реализацию, но любая попытка переопределить уже определенный тип приводит к неопределенному поведению (и, вероятно, но не обязательно, отклоняется компилятором).
Стандартный способ справиться с изменчивостью типов при использовании типов явной ширины с отформатированными функциями ввода-вывода - это использовать предоставленные для этой цели макросы , о которых вы уже знаете,В качестве альтернативы, если вы удовлетворены тем, что знаете применимые определения типов, используемых для всех интересующих платформ, вы можете написать соответствующие форматы напрямую.Или вы можете напрямую использовать стандартный тип по вашему выбору (, например, unsigned int
) или, для printf
, но не scanf
, привести аргумент к типу, соответствующему формату.
Не пренебрегайте альтернативой использования стандартных типов вместо псевдонимов типов с явной шириной.Первые являются более плавной альтернативой, когда их достаточно - нет необходимости в каких-либо специальных заголовках и плавная совместимость со всеми стандартными библиотечными функциями.
Очевидно, я могу изменить его на %lu
, но затем то же самоекод выдаст мне предупреждение при компиляции на x86.
Может быть, а может и нет. Тип unsigned long
имеет ширину 32 бита на glibc и для 32-битной x86. Я не уверен, что это тип, выбранный для int32_t
, но это одна из жизнеспособных альтернатив. То же самое верно даже для некоторых 64-битных платформ, таких как Win64. Для любой данной платформы, где обе альтернативы жизнеспособны, вы, вероятно, найдете несколько реализаций, которые выбирают одну, и некоторые, которые выбирают другую.