【问题标题】:Wrong definition of UINT16_C in arm-none-eabi-gcc?arm-none-eabi-gcc 中的 UINT16_C 定义错误?
【发布时间】:2021-12-03 12:07:41
【问题描述】:

我注意到 arm-none-eabi-gcc 10.2 以以下方式定义宏 UINTN_C(使用 -mcpu=cortex-m7 -std=c99 -g3 -O0 编译):

#define UINT32_C(x) __UINT32_C(x)  
#define UINT16_C(x) __UINT16_C(x) 

然后

#define __UINT32_C(c) c ## UL
#define __UINT16_C(c) c

C99 标准 (7.18.4.1 p2) 规定:

宏 UINTN_C(value) 应扩展为无符号整数常量 使用指定的值并输入 uint_leastN_t。

32 位版本确实扩展为无符号的 32 位表示(uint_least32_t 在此 CPU 上是 unsigned long)。

但是 16 位版本扩展为有符号表示:UINT16_C(1) 扩展为 1,其类型为 int

是不是和标准相矛盾?有没有可以解决这个问题的 gcc 选项?

为什么不做类似#define __UINT16_C(c) ((uint_least16_t)(c)) 的事情?

【问题讨论】:

  • 您是否查看了相应的头文件以获取一些信息?
  • 是的,我在 gcc 安装的整个目录中对 __UINTN_C 进行了 grep,但没有找到
  • 看起来这是gcc中常用的定义,例如sites.uclouvain.be/SystInfo/usr/include/stdint.h.html
  • 嗯,我的 MinGW 安装显示例如 #define UINT32_C(val) (val##U),但我没有查看细节。
  • UINT32_C 也一样。问题是 16 位和 8 位

标签: c gcc c99


【解决方案1】:

C 无法识别类型小于intunsigned int 的数字文字的概念。在 int 为 32 位的平台上,表达式 (uint16_t)123 将作为类型 signed int 作为整数提升的结果,对于包含假定类型为 uint16_t 的数字文字的表达式来说,这有点不合逻辑行为方式与处理该类型的任何其他表达式的方式不一致。

【讨论】:

  • 我很惊讶(uint16_t)123 会表现得像一个有符号整数。如果这些新宏与其他标准不兼容,那么定义这些新宏 UINTN_C 的意义何在?
  • @GuillaumePetitjean:假设(uint32_t)-0x9000, a platform where int` 是16 位,将产生0x00007000 而不是FFFF7000 的值。真正的问题是委员会无法决定是添加真正的固定大小的数字类型还是允许使用旧编译器在合适的 typedef 帮助下处理使用新类型的代码,因此最终会出现一个令人讨厌的大杂烩,例如两个uint16_t 值相乘可能会在某些编译器中触发无意义的行为。
  • @GuillaumePetitjean:我认为标准的作者认为,在大多数情况下,在将较小的无符号类型提升为有符号的行为之间存在已定义的差异,有符号的行为更合乎逻辑,并且在无符号算术可以定义行为但有符号算术不会定义的情况下,唯一不会以相同方式处理它们的实现将是那些针对无法有效处理全角无符号数学的晦涩平台的实现。尽管如此,当乘以 uint16_t 值时,gcc 有时会表现得毫无意义。
  • " 给定类似 (uint32_t)-0x9000 的东西,int` 为 16 位的平台将产生 0x00007000 而不是 FFFF7000 的值" 你确定吗? C99 标准规定 (6.4.4.1) 不带后缀的整数常量的类型是列表中第一个可以表示其值的类型,列表为:int、unsigned int、long int、unsigned long int 等。 .. 所以对我来说 -0x9000 应该是 16 位整数机器上的 long int 类型。那么uint32_t的演员应该转换为FFFF7000
  • @GuillaumePetitjean:十六进制文字和十进制文字的规则不同。没有后缀的十进制文字永远不会有符号,但介于 INT_MAX 和 UINT_MAX 之间的无后缀十六进制文字是无符号的。如果从头开始设计一门语言,C 的许多类型规则将没有意义,但旨在最大限度地与为各种实现编写的代码兼容,这些实现在向语言添加无符号类型时应用略有不同的语义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-19
相关资源
最近更新 更多