Ven*_*emo 7 c gcc arm cortex-m
我正在使用arm-none-eabi-gcc7.4 为基于 ARM Cortex-M4 的微控制器(特别是 EFM32WG940,但这应该与问题无关)编译“裸机”程序。
据我所知,sizeof(int)和sizeof(long int)与未签名的对应物一起都是4. 实际上,您必须输入long long int才能获取 64 位整数(或int64_t),因此long int似乎完全是多余的。
在这种环境下,为什么__UINT32_TYPE__ 预定义宏定义为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是使用这样的格式宏:虽然实际上并没有回答我的问题,但如果代码不是那么丑陋,并且一些静态分析器没有问题,那将是最好的。inttypes.hprintf("hello %" PRIu32, i);
我不想破解我所有的 printf 调用,而是想了解为什么uint32_t需要在这个平台unsigned long int上而不是unsigned int在这个平台上,以及如何改变它。
据我所知,
sizeof(int)和 以及sizeof(long int)它们的无符号对应项都是 4。您实际上必须键入long long int才能获得 64 位整数(或int64_t),因此long int似乎完全是多余的。
C 语言没有指定标准整数类型的精确宽度。相反,它指定每个值必须表示的最小范围。这使得 C 语言能够以自然的方式针对不同架构的目标进行编写。特别是,符合标准的实现可以为ints 提供少至 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]的自然选择(总共正好32 位,没有填充位) ,以及作为二进制补码实现的签名版本)。对于某些受支持的体系结构来说,长版本是唯一正确的选择,并且它们是其余大多数体系结构可接受的选择之一。通过选择长版本,glibc 只需要为 64 位平台的子集(或许还有一些具有奇怪整数类型的平台)做出例外。int32_t
没有任何要求,也没有理由对任何期望进行选择,并且当int它们满足要求时unsigned int将选择类型,除非它们是满足要求的唯一可用类型。int32_tuint32_t
有没有办法改变
uint32_t呢unsigned int?
您的 C 代码没有一致的方法来更改uint32_t实现提供的定义。您可以尝试修改 C 实现来进行更改,或者您可以选择完全不同的实现,但任何重新定义已定义类型的尝试都会产生未定义的行为(并且可能但不一定会被编译器拒绝)。
将显式宽度类型与格式化 I/O 函数一起使用时,处理类型可变性的标准方法是使用为此目的提供的宏,您已经了解了这一点。或者,如果您确信自己知道所有感兴趣的平台所涉及的类型的适用定义,那么您可以直接编写适当的格式。或者您可以直接使用您选择的标准类型(例如 unsigned int),或者, forprintf但不是scanf,将参数转换为与格式匹配的类型。
不要轻易放弃使用标准类型而不是显式宽度类型别名的替代方案。前者是一种更流畅的替代方案,只要它们足够了——不需要任何特殊的标头,并且与所有标准库函数具有流畅的互操作性。
显然我可以将其更改为
%lu,但在 x86 上编译时相同的代码会给我一个警告。
也许会,也许不会。unsigned long32 位 x86 的 glibc 上的类型也是 32 位宽。我不确定它是否是那里选择的类型int32_t,但它是可行的替代方案之一。即使对于某些 64 位平台(例如 Win64)也是如此。对于任何两种选择都可行的给定平台,您可能会发现一些实现选择其中一种,而另一些实现则选择另一种。