c语言 - 为什么十六进制整数常量不能为负数?



此表显示类型是该值可以容纳的第一个类型。使用 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和/或lll的十进制数字序列,任何大小写[大写或小写])。
  • 进制常量是以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_MAXint

对十进制输入执行相同的操作会显示所需的类型:ptype -16 type = int

16适合int,所以它是int。 确定类型后,该类型的否定是明确定义的,因此表达式的值-16

所以 -1 = 0 -1 = -1,又名负整数?我不明白这句话。

考虑-10 - 1使用int常量01,并且是值为 -1 且类型为int的表达式。

但是

当解释为有符号整数时0xFFFFFFF0是-16,那么为什么它不能适合int类型呢?

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

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

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

最新更新