【发布时间】:2023-01-19 07:18:01
【问题描述】:
你能告诉我数字后面的 u 到底是什么意思吗,例如:
#define NAME_DEFINE 1u
【问题讨论】:
标签: c
你能告诉我数字后面的 u 到底是什么意思吗,例如:
#define NAME_DEFINE 1u
【问题讨论】:
标签: c
C 代码中的整数字面量(如 1)始终属于 int 类型。 int 与 signed int 相同。将 u 或 U (等效)添加到文字以确保它是 unsigned int,以防止各种意外错误和奇怪的行为。
这种错误的一个例子:
在 int 为 16 位的 16 位机器上,此表达式将产生负值:
long x = 30000 + 30000;
这 30000 个字面量都是 int,并且由于两个操作数都是 int,所以结果将是 int。一个 16 位有符号整数只能包含最大 32767 的值,因此它会溢出。 x 因此会得到一个奇怪的负值,而不是预期的 60000。
代码
long x = 30000u + 30000u;
但是会按预期运行。
【讨论】:
this expression will result in a negative value。好吧,否则恶魔会飞出你的鼻子,因为整数溢出是未定义的行为。
gcc 例如至少有 20 种情况,它不考虑整数溢出来换行,因此它可以执行优化。一个简单的例子是像 a - 8 < 42 这样的表达式,如果 a 是有符号类型 gcc 可以将表达式简化为 a < 50。
这是一种定义方式未签名文字整数常量。
【讨论】:
这是一种告诉编译器常量 1 用作无符号整数的方法。一些编译器假定任何没有像“u”这样的后缀的数字都是 int 类型的。为避免这种混淆,建议在将常量用作无符号整数时使用像“u”这样的后缀。其他类似的后缀也存在。例如,使用 float 'f'。
【讨论】:
int、long和long long中第一个可以保存值(如果有)的类型。
它的意思是“unsigned int”,基本上它的功能类似于强制转换,以确保在编译时将数字常量转换为适当的类型。
【讨论】:
代码中的十进制文字(八进制和十六进制文字的规则不同,请参阅https://en.cppreference.com/w/c/language/integer_constant)具有int、long或long long类型之一。从这些中,编译器必须选择足够大以容纳该值的最小类型。请注意,不考虑类型 char、signed char 和 short。例如:
0 // this is a zero of type int
32767 // type int
32768 // could be int or long: On systems with 16 bit integers
// the type will be long, because the value does not fit in an int there.
如果给这样的数字添加一个u 后缀(大写的U 也可以),编译器将不得不从unsigned int、unsigned long 和unsigned long long 中选择最小的类型。例如:
0u // a zero of type unsigned int
32768u // type unsigned int: always fits into an unsigned int
100000u // unsigned int or unsigned long
最后一个示例可用于显示与演员表的区别:
100000u // always 100000, but may be unsigned int or unsigned long
(unsigned int)100000 // always unsigned int, but not always 100000
// (e.g. if int has only 16 bit)
旁注:在某些情况下,添加 u 后缀是确保计算正确性的正确做法,正如 Lundin 的回答所证明的那样。然而,也有严格禁止混合有符号和无符号类型的编码指南,即使是以下声明
unsigned int x = 0;
被归类为不合格,必须写成
unsigned int x = 0u;
这可能会导致这样一种情况,即经常处理无符号值的开发人员养成了在任何地方向文字添加 u 后缀的习惯。但是,请注意,更改签名会导致在各种情况下出现不同的行为,例如:
(x > 0)
可以(取决于 x 的类型)意味着不同于
(x > 0u)
幸运的是,编译器/代码检查器通常会就可疑情况向您发出警告。尽管如此,添加 u 后缀应该慎重考虑。
【讨论】: