我正在学习不同数据类型的特征。例如,该程序越来越多地使用四种不同格式打印2的幂:#include<stdio.h>
int main(int argc, char *argv[]){
int i, val = 1;
for (i = 1; i < 35; ++i) {
printf("%15d%15u%15x%15o\n", val, val, val, val);
val *= 2;
}
return 0;
}
unsigned
有效。 2147483648
升至integer
。 -2147483648
升至2147483647
。但为什么它变得消极?
我有一个理论:是因为我们可以在32位机器上表示的最大有符号整数是{{1}}吗?如果是这样,为什么它会返回负数?
答案 0 :(得分:5)
首先,您应该了解此程序是 undefined 。它会导致带符号的整数溢出,并在C标准中声明 undefined 。
技术原因是没有行为可以预测,因为负数允许不同的表示,并且表示中甚至可能有填充位。
在您的情况下,您看到负数的最可能原因是您的机器使用 2补码(查找)来表示负数,而算术运算在没有溢出检查的位上。因此,最高位是符号位,如果您的值溢出到该位,它将变为负值。
答案 1 :(得分:2)
您描述的是由整数溢出引起的UB。由于行为未定义,任何事情都可能发生(“当编译器遇到[给定的未定义构造]时,让恶魔飞出你的鼻子是合法的”),但实际上发生了什么一些机器(我怀疑你的机器)是这样的:
您从int val = 1;
开始。它以二进制形式表示0b00...1
。每次val *= 2;
该值乘以2,因此表示更改为0b00...10
,然后更改为0b00...100
,依此类推(1
位每次移动一步) 。您上次val *= 2;
获得0b100...
。现在,使用2的补码(这是我猜你的机器使用的,因为它很常见),实际上-1 * 0b1000...
的值是-2147483648
请注意,尽管这可能是您的计算机上真正发生的事情,但它不会被信任或被认为是&#34;权利&#34;要发生的事情,因为如前所述,这是UB
答案 2 :(得分:-1)
在此程序中,val
值将溢出,如果它是32位机器,因为整数的大小是4个字节。现在,我们在数学中有两种类型的值,正面和负面,因此要进行涉及否定结果的计算,我们在C语言中使用符号表示,即int
或char
。
让我们以char
为例,范围-128到127,unsigned char
范围0-255。
它告诉我,范围分为两部分用于签名表示。因此,对于任何已签名的变量,如果它超过其+ ve值的范围,则它将变为负值。就像char
的情况一样,当值超过127时,它变为-ve。并且假设如果您向任何char
或unsigned char
变量添加300,则会翻转并从零开始。
char a=2;
a+=300;
价值是多少?现在你知道char
的最大值是255(总共256个值,包括零),所以300-256 = 44 + 2 = 46。
希望这有帮助