我正在使用arm-none-eabi-gcc
7.4为基于ARM Cortex-M4的微控制器(特别是EFM32WG940编译“裸机”程序,但这应该与问题无关)。
据我所知,sizeof(int)
和sizeof(long int)
以及他们未签名的对手都是4
。你实际上必须键入long long int
来获得64位整数(或int64_t
),所以long int
似乎完全是多余的。
在这种环境下,为什么__UINT32_TYPE__
predefined macro定义为long unsigned int
?
有没有办法改变uint32_t
而不是unsigned int
?
通常这不会打扰我,但它导致printf
给我一个困难的时间因为-Wformat
。考虑像:printf("hello %u\n", i);
(假设i
是uint32_t
),它给了我一个警告,因为%u
期待unsigned
但uint32_t
是unsigned long
。显然我可以将它改为%lu
,但是当在x86上编译时,相同的代码会给我一个警告。
编辑:
是的,沉默-Wformat
的一种方法是使用来自format macros的inttypes.h
像这样:printf("hello %" PRIu32, i);
虽然实际上没有回答我的问题,但如果代码不那么难看,那将是很好的,并且一些静态分析仪没有问题用它。
我想知道为什么uint32_t
需要在这个平台上使用unsigned long int
而不是unsigned int
,而不是黑客攻击我的所有printf调用,以及如何改变它。
据我所知,
sizeof(int)
和sizeof(long int)
以及他们的无符号对应物都是4.你实际上必须输入long long int
来获得64位整数(或int64_t
),所以long int
似乎完全是多余的。
C语言没有指定标准整数类型的确切宽度。相反,它指定了每个必须表示的最小值范围。这允许以自然的方式为不同架构的目标编写C.特别是,符合要求的实现可以为qazxswpo提供少至15个值位,而int
必须至少为31,long int
必须至少为63.有符号整数类型也有一个符号位,而无符号对应一个附加值位。 (其中任何一个也可能有填充位,但这并不常见。)所以不,long long int
不是多余的,至少不是语义意义上的。
在这种环境中,为什么
long int
预定义的宏被定义为__UINT32_TYPE__
?
首先,long unsigned int
是一个glibc实现细节。因此,提出这个问题的唯一合理答案是“因为__UINT32_TYPE__
是为unsigned long int
选择的类型。”但我带你去问其实为什么选择这种类型。我不能明确地说明GCC / glibc开发人员在这里做出决定的原因,但我认为我会在他们的位置做出相同的选择,他们试图支持各种各样的架构。
因为uint32_t
和long int
分别保证至少有31和32个值位(并且unsigned long int
和int
不是),长版本是[unsigned int
] u
在那些实际满足其要求的平台上的自然选择(正好32位总数,无填充位,签名版本实现为二进制补码)。对于某些受支持的体系结构,长版本是唯一正确的选择,对于大多数其他体系结构而言,它们是可接受的选择之一。通过选择长版本,glibc只需要为64位平台的子集做出例外,也许只有少数平台有奇数整数类型。
当int32_t
和int
满足其要求时,unsigned int
和int32_t
将被选为uint32_t
和uint32_t
的类型,除非它们是满足要求的唯一可用类型,否则没有任何要求,也没有任何理由可以预期。
有没有办法改变
unsigned int
而不是uint32_t
?
您的C代码没有一致的方法来更改实现提供的the macros provided for that purpose的定义。您可以尝试攻击您的C实现来进行更改,或者您可以选择完全不同的实现,但任何重新定义已定义类型的尝试都会产生未定义的行为(可能但不一定会被编译器拒绝)。
使用带有格式化I / O函数的显式宽度类型时,处理类型可变性的标准方法是使用unsigned int
,您已经知道它。或者,如果您对所有感兴趣的平台所涉及的类型的适用定义感到满意,那么您可以直接编写适当的格式。或者您可以直接使用您选择的标准类型(例如printf
),或者对于scanf
而不是%lu
,将参数转换为与格式匹配的类型。
不要轻易忽略使用标准类型而不是显式宽度类型别名的替代方法。前者是一个更平滑的替代方案,它们就足够了 - 不需要任何特殊的头文件,以及与所有标准库函数的平滑互操作性。
显然我可以将它改为
unsigned long
,但是当在x86上编译时,相同的代码会给我一个警告。
也许它会,也许它不会。对于32位x86,类型int32_t
在glibc上也是32位宽。我不确定它是否是那里为qazxswpoi选择的类型,但它是可行的替代品之一。即使对于某些64位平台(例如Win64)也是如此。对于任何两种替代方案都可行的给定平台,您可能会找到一些选择一个的实现,而另一些选择另一个。