为什么`uint32_t`在arm-none-eabi GCC上的type unsffed为`unsigned long`,以及如何改变它?

问题描述 投票:0回答:1

我正在使用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);(假设iuint32_t),它给了我一个警告,因为%u期待unsigneduint32_tunsigned long。显然我可以将它改为%lu,但是当在x86上编译时,相同的代码会给我一个警告。

编辑:

是的,沉默-Wformat的一种方法是使用来自format macrosinttypes.h像这样:printf("hello %" PRIu32, i);虽然实际上没有回答我的问题,但如果代码不那么难看,那将是很好的,并且一些静态分析仪没有问题用它。

我想知道为什么uint32_t需要在这个平台上使用unsigned long int而不是unsigned int,而不是黑客攻击我的所有printf调用,以及如何改变它。

c gcc arm cortex-m
1个回答
1
投票

据我所知,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_tlong int分别保证至少有31和32个值位(并且unsigned long intint不是),长版本是[unsigned int] u在那些实际满足其要求的平台上的自然选择(正好32位总数,无填充位,签名版本实现为二进制补码)。对于某些受支持的体系结构,长版本是唯一正确的选择,对于大多数其他体系结构而言,它们是可接受的选择之一。通过选择长版本,glibc只需要为64位平台的子集做出例外,也许只有少数平台有奇数整数类型。

int32_tint满足其要求时,unsigned intint32_t将被选为uint32_tuint32_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)也是如此。对于任何两种替代方案都可行的给定平台,您可能会找到一些选择一个的实现,而另一些选择另一个。

© www.soinside.com 2019 - 2024. All rights reserved.