此表显示类型是该值可以容纳的第一个类型。使用 gdb 检查0xFFFFFFF0
显示它是一个unsigned type
:
(gdb) ptype 0xFFFFFFF0
type = unsigned int
但是0xFFFFFFF0
在解释为有符号整数时是-16
的,那么为什么它不能适合int
类型呢?对十进制输入执行相同的操作会显示所需的类型:
ptype -16
type = int
我也想在上面的同一个链接中询问这句话:
没有负整数常量。-1 等表达式将一元减号运算符应用于常量表示的值,这可能涉及隐式类型转换。
所以 -1 = 0 -1 = -1,又名负整数?我不明白这句话。
C 中没有负整数常量。
整数常量的语法为:
- 十进制常量是不以
0
开头和可选后缀(u
和/或l
或ll
的十进制数字序列,任何大小写[大写或小写])。
八 - 进制常量是以
0
开头的八进制数字序列,后缀可选。 - 十六进制常量
0x
后跟一系列十六进制数字(任何情况)。
这些都没有减号。C 中的所有整数常量都是具有非负值的数字。在 C 代码中出现带有常量的减号,如在-34
中,它是两个单独的标记:一元否定运算符后跟一个常量。
为常量选择类型的目的是选择可以表示其值的类型。作为十六进制数字,FFFFFFF016的值为 4,294,967,280。如果0xFFFFFFF0
被做成一个32位int
,这个整数的值将是2补码中的-16,或者补码或符号和幅度中的其他值。它不会是4,294,967,280。因此,32 位int
不能表示此数字的值,因此编译器不会对该类型使用 32 位int
。
也没有负浮点常量。在某些情况下,枚举常量和字符常量可能是负数。
它与常量是十六进制无关 - 它只与常量的值和多少位有关。
键入常量文本(不带类型后缀)的规则非常简单。 它只是检查该值是否在各种有符号和无符号整数类型的范围内,从 int 开始,逐渐变大的类型,直到找到合适的类型。 它会先尝试给定大小的有符号类型,然后再尝试该大小的无符号类型。
如果您使用十进制整数,也会发生同样的事情:
(gdb) ptype 4294967280
type = unsigned int
这里4294967280是 0xfffffff0 的十进制值。 由于此值超出了int
的范围,但在unsigned int
的范围内,因此就是这样。 尝试一个数字再加一个数字(十六进制或十进制),你会得到long long
,因为它超出了unsigned int
的范围。
使用负数,通常会得到一个有符号类型:
(gdb) ptype -0x10
type = int
但是,-
并不是常量的一部分,它是应用于文本的运算符,不会影响其类型。 所以你看
(gdb) p 0xfffffff0
$1 = 4294967280
(gdb) p -0xfffffff0
$2 = 16
(gdb) ptype -0xfffffff0
type = unsigned int
(gdb) ptype 4294967280
type = unsigned int
(gdb) p -4294967280
$3 = 16
(gdb) ptype -4294967280
type = unsigned int
注意最后一个 - 一个十进制常量,对于int
来说太大了(但在unsigned
范围内),给出了惊人的输出。 尽管 C 规范似乎明确指出,无论值如何,十进制常量将始终是有符号的,而不是无符号的。
数字更大
(gdb) p 0xffffffff0
$4 = 68719476720
(gdb) ptype 0xffffffff0
type = long long
(gdb) p -0xffffffff0
$5 = -68719476720
缩短答案
为什么十六进制整数常量不能为负数?
在 C 中,所有整数常量都是非负数(0 或更多),因为这就是语言的定义方式。
但是0xFFFFFFF0解释为有符号整数时是 -16,那么为什么它不能适合 int 类型呢?
0xFFFFFFF0
适合的第一种类型是unsigned
,而不是大于INT_MAX
int
。
对十进制输入执行相同的操作会显示所需的类型:ptype -16 type = int
16
适合int
,所以它是int
。 确定类型后,该类型的否定是明确定义的,因此表达式的值-16
。
所以 -1 = 0 -1 = -1,又名负整数?我不明白这句话。
考虑-1
和0 - 1
使用int
常量0
和1
,并且是值为 -1 且类型为int
的表达式。
当解释为有符号整数时0xFFFFFFF0是-16,那么为什么它不能适合int类型呢?
当你说"解释为"时,你无法区分数字的外部表示和内部表示。 我认为所讨论的常量以十六进制表示的事实导致了此错误。我怀疑你会建议4294967280应该解释为 -16(十进制),但这与您对十六进制版本的建议完全相似。
事实是,为此目的,十六进制整数常量不应被解释为位模式。 它们是数字的十六进制表示形式。 它们是隐式正数,没有以整数常量的词法形式提供表示负数的机制。 (负数可以形成为涉及整数常量和一元-
运算符的表达式。
除此之外,这还支持可移植性,因为 C 没有指定各种整数类型的确切大小,并且实现在实践中确实有所不同。 C 还允许三种不同的选择来表示负整数,尽管现在实现非常一致地使用二进制补码格式。给定的整数常量,无论是以八进制、十进制还是十六进制表示,都将被每个 C 实现解释为相同的数值(尽管可能有一些没有数据类型可以表示该值)。