gpt4 book ai didi

c - 保护十六进制文字后的 "U"后缀

转载 作者:太空狗 更新时间:2023-10-29 17:19:00 25 4
gpt4 key购买 nike

我和我的同事就十六进制表示的文字后的 U 后缀存在一些争论。请注意,这不是关于此后缀的含义或它的作用的问题。我在这里找到了其中的几个主题,但我还没有找到我的问题的答案。

一些背景信息:

我们正在努力制定一套我们都同意的规则,并从那时起将其用作我们的风格。我们有一份 2004 Misra C 规则的副本,并决定以此为起点。我们对完全符合 Misra C 不感兴趣;我们正在精心挑选我们认为最能提高效率和稳健性的规则。

上述指南中的规则 10.6 规定:

A “U” suffix shall be applied to all constants of unsigned type.

我个人认为这是一个很好的规则。它需要很少的努力,看起来比显式转换更好,并且更明确地显示了常量的意图。对我来说,将它用于所有无符号常量是有意义的,而不仅仅是数字,因为通过允许异常不会强制执行规则,尤其是对于常量的常用表示。

然而,我的同事认为十六进制表示不需要后缀。主要是因为我们几乎只使用它来设置微 Controller 寄存器,而将寄存器设置为十六进制常量时,符号无关紧要。

我的问题

我的问题不是关于谁对谁错的问题。它是关于找出是否存在后缀的缺失或存在会改变操作结果的情况。有没有这样的情况,还是一致性的问题?

编辑:澄清;特别是关于通过为它们分配十六进制值来设置微 Controller 寄存器。在这种情况下,后缀会有所不同吗?我感觉不会例如,飞思卡尔处理器专家将所有寄存器分配生成为无符号。

最佳答案

在所有十六进制常量上附加一个 U 后缀会使它们如您已经提到的那样无符号。当这些常量与有符号值一起用于操作时,尤其是比较时,这可能会产生不良副作用。

这是一个病态的例子:

#define MY_INT_MAX  0x7FFFFFFFU   // blindly applying the rule

if (-1 < MY_INT_MAX) {
printf("OK\n");
} else {
printf("OOPS!\n");
}

有符号/无符号转换的 C 规则是精确指定的,但有点违反直觉,所以上面的代码确实会打印 OOPS

MISRA-C 规则非常精确,因为它规定“U”后缀应应用于所有无符号类型的常量。无符号 一词具有深远的影响,事实上,大多数常量实际上不应该被认为是无符号的。

此外,C 标准在十进制和十六进制常量之间做了细微的区别:

  • 如果十六进制常量的值可以用无符号整数类型表示,而不是 int 和更大类型的相同大小的有符号整数类型,则它被认为是无符号的。

这意味着在 32 位 2 的补码系统上,2147483648 是一个 long 或一个 long long0x80000000 是一个 unsigned int。在这种情况下,附加 U 后缀可能会使这一点更加明确,但避免潜在问题的真正预防措施是强制编译器完全拒绝有符号/无符号比较:gcc -Wall -Wextra -Werror clang -Weverything -Werror 是救命稻草。

以下是它的糟糕程度:

if (-1 < 0x8000) {
printf("OK\n");
} else {
printf("OOPS!\n");
}

上面的代码应该在 32 位系统上打印 OK,在 16 位系统上打印 OOPS。更糟糕的是,嵌入式项目使用过时的编译器仍然很常见,这些编译器甚至没有为这个问题实现标准语义。

对于您的具体问题,微处理器寄存器的定义值专门用于通过赋值设置它们(假设这些寄存器是内存映射的),根本不需要 U 后缀。寄存器左值应具有无符号类型,十六进制值将根据其值是有符号还是无符号,但操作将进行相同。设置有符号数或无符号数的操作码在您的目标架构和我见过的任何架构上都是相同的。

关于c - 保护十六进制文字后的 "U"后缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45621041/

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