gpt4 book ai didi

c - 为什么在 arm-none-eabi GCC 上将 `uint32_t` 类型定义为 `unsigned long`,以及如何更改它?

转载 作者:太空宇宙 更新时间:2023-11-04 03:11:35 30 4
gpt4 key购买 nike

我正在使用 arm-none-eabi-gcc 7.4 为基于 ARM Cortex-M4 的微 Controller (特别是 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); (假设 iuint32_t )
这给了我一个警告,因为 %u预计 unsigned但是 uint32_tunsigned long .显然我可以把它改成 %lu但是同样的代码在 x86 上编译时会给我一个警告。

编辑:

是的,一种静音方式 -Wformat是使用 format macros来自 inttypes.h像这样:printf("hello %" PRIu32, i);这虽然实际上并没有回答我的问题,但如果代码不是那么难看的话就可以了,并且一些静态分析器没有问题。

我不想破解我所有的 printf 调用,而是想了解为什么 uint32_t需要unsigned long int而不是 unsigned int在这个平台上,以及如何改变它。

最佳答案

As far as I see, sizeof(int) and sizeof(long int) alongside with their unsigned counterparts are both 4. You actually have to type long long int to get a 64-bit integer (or int64_t), so long int seems to be entirely superfluous.



C 语言没有指定标准整数类型的确切宽度。相反,它指定了每个值必须代表的最小范围。这允许针对不同架构的目标以自然的方式编写 C。特别是,符合要求的实现可以提供 int s 只有 15 个值位,而 long int必须至少有 31 个,并且 long long int必须至少为 63。有符号整数类型也有一个符号位,而无符号整数类型也有一个额外的值位。 (其中任何一个也可能有填充位,尽管这种情况并不常见。)所以不, long int不是多余的,至少在语义上不是多余的。

In this environment, why is the __UINT32_TYPE__ predefined macro defined to long unsigned int?



首先, __UINT32_TYPE__是 glibc 实现细节。因此,对该问题的唯一合理答案是“因为 unsigned long int 是为 uint32_t 选择的类型。”但我带你实际上是问为什么首先选择这种类型。我无法在这里明确说明 GCC/glibc 开发人员做出决定的原因,但我认为我会在他们的位置做出相同的选择,他们试图支持各种架构。

因为 long intunsigned long int保证分别至少有 31 和 32 个值位(而 intunsigned int 不是),长版本是 [ u 的自然选择] int32_t在它们实际上满足其要求的那些平台上(总共正好 32 位,没有填充位,并且有符号版本实现为二进制补码)。对于某些受支持的体系结构,长版本是唯一正确的选择,并且它们是其余大多数体系结构可接受的选择之一。通过选择长版本,glibc 只需要对 64 位平台的一个子集进行异常(exception)处理,也许还有一些具有奇怪整数类型的平台。
int 没有任何要求,也没有理由为任何期望提供理由。和 unsigned int将是为 int32_t 选择的类型和 uint32_t当它们满足要求时,除非它们是满足要求的唯一可用类型。

Is there a way to change uint32_t to be unsigned int instead?



您的 C 代码没有一致的方法来更改 uint32_t 的定义。由实现提供。您可以尝试修改 C 实现以进行更改,或者您可以选择完全不同的实现,但是任何重新定义已定义类型的尝试都会产生未定义的行为(并且可能但不一定会被编译器拒绝)。

在格式化 I/O 函数中使用显式宽度类型时处理类型可变性的标准方法是使用 the macros provided for that purpose ,你已经知道了。或者,如果您对所有感兴趣的平台所涉及的类型的适用定义感到满意,那么您可以直接编写适当的格式。或者您可以直接使用您选择的标准类型(例如 unsigned int )或者,对于 printf但不是 scanf , 将参数强制转换为与格式匹配的类型。

不要轻易放弃使用标准类型而不是显式宽度类型别名的替代方案。前者是一种更流畅的替代方案——不需要任何特殊的头文件,并且与所有标准库函数具有平滑的互操作性。

Obviously I can change it to %lu but then the same code will give me a warning when compiled on x86.



也许会,也许不会。类型 unsigned long对于 32 位 x86,在 glibc 上也是 32 位宽。我不确定它是否是为 int32_t 选择的类型那里,但它是可行的选择之一。即使对于某些 64 位平台(例如 Win64)也是如此。对于两种替代方案都可行的任何给定平台,您可能会发现一些实现选择一种,而另一些实现选择另一种。

关于c - 为什么在 arm-none-eabi GCC 上将 `uint32_t` 类型定义为 `unsigned long`,以及如何更改它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55782246/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com