有人可以向我解释以下代码输出:
void myprint(unsigned long a)
{
printf("Input is %lx\n", a);
}
int main()
{
myprint(1 << 31);
myprint(0x80000000);
}
输出
gcc main.c
:Input is ffffffff80000000
Input is 80000000
为什么
(1 << 31)
被视为有符号而 0x80000000
被视为无符号? 最佳答案
在 C 中,表达式的结果取决于操作数(或某些操作数)的类型。特别是, 1
是 int
(有符号),因此 1 << n
也是 int
。0x80000000
的类型(包括符号)由规则 here 决定,它取决于系统上 int
和其他未指定的整数类型的大小。选择一种类型,使得 0x80000000
(一个很大的正数)在该类型的范围内。
如果您有任何误解:文字 0x80000000
是一个很大的正数。人们有时错误地将其等同于负数,将值与表示混淆。
在您的问题中,您说“为什么 0x80000000 被视为无符号?”。但是,您的代码实际上并不依赖于 0x80000000
的签名。您对它所做的唯一一件事就是将其传递给采用 unsigned long
参数的函数。所以它是签名还是未签名并不重要;当传递给转换时,它被转换为具有相同值的 unsigned long
。 (由于 0x80000000
在 unsigned long
的最小保证范围内,因此它不可能超出范围)。
所以,这是 0x80000000
处理。 1 << 31
怎么样?如果您的系统具有 32 位 int(或更窄),则由于有符号算术溢出,这会导致 undefined behaviour。 ( Link to further reading )。如果您的系统有更大的整数,那么这将产生与 0x80000000
行相同的输出。
如果您改用 1u << 31
,并且您有 32 位整数,则没有未定义的行为,并且您可以保证看到程序输出 80000000
两次。
由于您的输出不是 80000000
,因此我们可以得出结论,您的系统具有 32 位(或更窄)int,并且您的程序实际上会导致未定义的行为。如果 0x80000000
是 32 位,则 unsigned int
的类型将为 int
,否则为 unsigned long
。
关于c - 未签名和已签名扩展,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36981081/