为什么十六进制整数常量不能为负数?

Why can't a hexadecimal integer constant be negative?

This table 显示类型是第一个适合该值的类型。用 gdb 检查 0xFFFFFFF0 表明它是一个 unsigned type:

(gdb) ptype 0xFFFFFFF0
type = unsigned int

但是 0xFFFFFFF0 被解释为有符号整数时是 -16 那么为什么它不适合 int 类型呢?对十进制输入执行相同的操作会显示所需的类型:

ptype -16
type = int

我也想问一下上面同link中的这句话:

There are no negative integer constants. Expressions such as -1 apply the unary minus operator to the value represented by the constant, which may involve implicit type conversions.

所以 -1 = 0 -1 = -1,也就是负整数?这句话我没看懂。

它与常量是否为十六进制无关——它只与常量的值及其位数有关。

常量文字(没有类型后缀)的类型化规则非常简单。它只是检查该值是否在各种有符号和无符号整数类型的范围内,从 int 开始逐渐变大,直到找到适合的类型。它在给定大小的无符号类型之前尝试给定大小的有符号类型。

如果你使用十进制整数,同样的事情会发生:

(gdb) ptype 4294967280
type = unsigned int

这里的4294967280是0xfffffff0的十进制值。由于此值超出了 int 的范围,但在 unsigned int 的范围内,所以就是这样。尝试多一位数字(十六进制或十进制),您将得到 long long,因为它超出了 unsigned int.

的范围

使用负数,你通常会得到一个带符号的类型:

(gdb) ptype -0x10
type = int

然而,- 并不是常量的真正组成部分,它是一个应用于文字的运算符,不会影响其类型。所以你看

(gdb) p 0xfffffff0
 = 4294967280
(gdb) p -0xfffffff0
 = 16
(gdb) ptype -0xfffffff0
type = unsigned int
(gdb) ptype 4294967280
type = unsigned int
(gdb) p -4294967280
 = 16
(gdb) ptype -4294967280
type = unsigned int

注意最后一个——一个十进制常量,对于 int 来说太大了(但在 unsigned 的范围内)给出了一个令人惊讶的输出。尽管事实上 C 规范似乎明确指出十进制常量将始终是有符号的,而不是无符号的,无论其值如何。

数字更大

(gdb) p 0xffffffff0
 = 68719476720
(gdb) ptype 0xffffffff0
type = long long
(gdb) p -0xffffffff0
 = -68719476720

C语言中没有负整数常量

整数常量的语法是:

  • 十进制常量是不以 0 开头并带有可选后缀(u and/or lll 的十进制数字序列要么订购任何大小写 [大写或小写]).
  • 八进制常量是以 0 和可选后缀开头的八进制数字序列。
  • 十六进制常量是 0x 后跟一系列十六进制数字,大小写不限。

None 其中有一个减号。 C 中的所有整数常量都是具有非负值的数字。在 C 代码中减号与常量一起出现的地方,如 -34,它是两个独立的标记:一元取反运算符后跟一个常量。

select常量类型的目标是 select 一个可以表示其值的类型。作为十六进制数,FFFFFFF016 的值为 4,294,967,280。如果 0xFFFFFFF0 被设为 32 位 int,则该 int 的值将是 −16 的二进制补码或其他一些值的补码或 sign-and-magnitude。它不会是 4,294,967,280。所以 32 位 int 不能表示这个数字的值,所以编译器不会使用 32 位 int 作为类型。

也没有负 floating-point 常量。枚举常量和字符常量在某些情况下可以为负数。

But 0xFFFFFFF0 is -16 when interpreted as a signed integer so why can't it fit in the int type?

当您说“解释为”时,您无法区分数字的外部表示和内部表示。我认为所讨论的常量以十六进制表示的事实是导致此错误的原因。我怀疑您会建议将 4294967280 解释为 -16(十进制),但这与您对十六进制版本的建议完全相似。

事实上,十六进制整数常量不能被解释为用于此目的的位模式。它们是数字的十六进制表示。它们是隐含的正数,没有以整数常量的词法形式提供的机制来表示负数。 (负数可以形成为 表达式 ,涉及整数常量和一元 - 运算符。)

除其他外,这支持可移植性,因为 C 没有指定各种整数类型的确切大小,并且实现在实践中也有所不同。 C 还允许三种不同的选择来表示负整数,尽管现在的实现非常一致地使用二进制补码格式。给定的整数常量,无论是以八进制、十进制还是十六进制表示,每个 C 实现都将解释为相同的数值(尽管可能有些没有可以表示该值的数据类型)。

缩短答案

Why can't a hexadecimal integer constant be negative?

在 C 语言中,所有整数常量都是 non-negative(0 或更多),因为这就是语言的定义方式。

But 0xFFFFFFF0 is -16 when interpreted as a signed integer so why can't it fit in the int type?

适合的第一个类型 0xFFFFFFF0unsigned,而不是 int,因为它大于 INT_MAX

Doing the same with a decimal input shows the desired type: ptype -16 type = int

16 适合 int,所以它是 int。类型确定后,that的取反定义明确,所以表达式的值为-16.

So -1 = 0 -1 = -1, AKA a negative integer? I don't understand this sentence.

考虑 -10 - 1 使用 int 常量 01 并且它们都是值为 -1 且类型为 int.