谁能给我解释一下下面的代码输出:
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
的类型将是 unsigned int
如果int
是 32 位,或 unsigned long
否则。
关于c - 未签名和已签名的扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36981081/