"Integer constant is so large that it is unsigned" 编译器警告理由
"Integer constant is so large that it is unsigned" compiler warning rationale
以下C/C++代码:
long long foo = -9223372036854775808LL; // -2^63
编译 (g++) 时出现警告
integer constant is so large that it is unsigned.
clang++ 给出了类似的警告。
感谢这个错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661。我现在明白为什么 GCC 会发出这个警告了。不幸的是,对错误报告的回应并没有很好地解释这种行为的原因。
问题:
- 为什么 32/16/8 位有符号整数常量的等效代码没有给出警告?
- GCC 和 Clang 都给出了这个警告,所以这显然是故意的行为,而不仅仅是 'to make it easier to parse,' 作为对错误报告的回应所建议的。为什么?
- C/C++ 标准是否强制要求这种行为?其他一些标准?
这与整数常量类型的定义方式有关。
首先,如gcc错误报告中所述,-9223372036854775808LL
实际上是两个标记:一元运算符-
和整数常量9223372036854775808LL
。所以警告只适用于后者。
C standard 的第 6.4.4.1p5 节指出:
The type of an integer constant is the first of the corresponding list in which its value can be represented.
基于此,没有后缀的十进制整数常量将根据值具有 int
、long
或 long long
类型。这些都是有符号的类型。因此任何小到适合 8 位或 16 位类型的值仍然具有 int
类型,而对于 32 位有符号整数来说太大的值将具有 long
或 long long
类型,具体取决于关于该系统上类型的大小。后缀为LL
的常量也是如此,但只尝试了long long
类型。
出现警告是因为您使用的值不在上述类型列表中。任何较小的值都会导致该值具有带符号类型,这意味着不会转换为无符号类型。
正如 bug 报告中或多或少有些困惑的人所说,整数常量 9223372036854775808LL
太大而无法放入 long long
.
对于十进制常量,标准在 6.4.4.1 中有一个列表(参见 ),描述了编译器将尝试赋予整数常量的类型。在这种情况下,类型的唯一有效选项是 (signed) long long
并且它不适合那里。然后 table 下的 §6 开始:
If an integer constant cannot be represented by any type in its list, it may have an
extended integer type, if the extended integer type can represent its value. /--/
If the list contains both signed and unsigned types, the extended integer type
may be signed or unsigned.
扩展整数类型在标准中是一个模糊但正式的术语。在这种情况下,编译器显然会尝试将常量压缩到适合的 unsigned long long
“扩展整数类型”中。这不是真正保证的行为,而是实现定义的。
然后将一元运算符 -
应用于产生警告的 unsigned long long
。
这就是limits.h等库头文件喜欢将LLONG_MIN
定义为
的原因
#define LLONG_MIN (-9223372036854775807LL - 1)
你可以做类似的事情来避免这个警告。或者更好的是,使用 LLONG_MIN
.
Why is no warning given for the equivalent code for a 32/16/8-bit signed integer constant?
常量不限于 8、16 或 32 位。它是第一种适合的类型,十进制 常量可以达到 至少 63 位。
9223372036854775808LL
超出了 OP 的 long long
范围,因为 9223372036854775808
需要 64 位。
-
应用 在 常量生成之后。
在 int,long,long long
as 32,32,64
位实现上:-2147483648
是类型 long long
,而不是 int
。
GCC and Clang both give this warning, so it is clearly intentional behavior and not just 'to make it easier to parse,' as is suggested in response to the bug report. Why?
无评论。 Link 没有提供信息。最好到这里数据。
Is this behavior mandated by the C/C++ standard? Some other standard?
是的,按照 C 标准。
以下C/C++代码:
long long foo = -9223372036854775808LL; // -2^63
编译 (g++) 时出现警告
integer constant is so large that it is unsigned.
clang++ 给出了类似的警告。
感谢这个错误报告:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661。我现在明白为什么 GCC 会发出这个警告了。不幸的是,对错误报告的回应并没有很好地解释这种行为的原因。
问题:
- 为什么 32/16/8 位有符号整数常量的等效代码没有给出警告?
- GCC 和 Clang 都给出了这个警告,所以这显然是故意的行为,而不仅仅是 'to make it easier to parse,' 作为对错误报告的回应所建议的。为什么?
- C/C++ 标准是否强制要求这种行为?其他一些标准?
这与整数常量类型的定义方式有关。
首先,如gcc错误报告中所述,-9223372036854775808LL
实际上是两个标记:一元运算符-
和整数常量9223372036854775808LL
。所以警告只适用于后者。
C standard 的第 6.4.4.1p5 节指出:
The type of an integer constant is the first of the corresponding list in which its value can be represented.
基于此,没有后缀的十进制整数常量将根据值具有 int
、long
或 long long
类型。这些都是有符号的类型。因此任何小到适合 8 位或 16 位类型的值仍然具有 int
类型,而对于 32 位有符号整数来说太大的值将具有 long
或 long long
类型,具体取决于关于该系统上类型的大小。后缀为LL
的常量也是如此,但只尝试了long long
类型。
出现警告是因为您使用的值不在上述类型列表中。任何较小的值都会导致该值具有带符号类型,这意味着不会转换为无符号类型。
正如 bug 报告中或多或少有些困惑的人所说,整数常量 9223372036854775808LL
太大而无法放入 long long
.
对于十进制常量,标准在 6.4.4.1 中有一个列表(参见 long long
并且它不适合那里。然后 table 下的 §6 开始:
If an integer constant cannot be represented by any type in its list, it may have an extended integer type, if the extended integer type can represent its value. /--/
If the list contains both signed and unsigned types, the extended integer type may be signed or unsigned.
扩展整数类型在标准中是一个模糊但正式的术语。在这种情况下,编译器显然会尝试将常量压缩到适合的 unsigned long long
“扩展整数类型”中。这不是真正保证的行为,而是实现定义的。
然后将一元运算符 -
应用于产生警告的 unsigned long long
。
这就是limits.h等库头文件喜欢将LLONG_MIN
定义为
#define LLONG_MIN (-9223372036854775807LL - 1)
你可以做类似的事情来避免这个警告。或者更好的是,使用 LLONG_MIN
.
Why is no warning given for the equivalent code for a 32/16/8-bit signed integer constant?
常量不限于 8、16 或 32 位。它是第一种适合的类型,十进制 常量可以达到 至少 63 位。
9223372036854775808LL
超出了 OP 的 long long
范围,因为 9223372036854775808
需要 64 位。
-
应用 在 常量生成之后。
在 int,long,long long
as 32,32,64
位实现上:-2147483648
是类型 long long
,而不是 int
。
GCC and Clang both give this warning, so it is clearly intentional behavior and not just 'to make it easier to parse,' as is suggested in response to the bug report. Why?
无评论。 Link 没有提供信息。最好到这里数据。
Is this behavior mandated by the C/C++ standard? Some other standard?
是的,按照 C 标准。