我无法找到此代码的输出。请帮我查一下以下输出段的输出。
#include<stdio.h>
int main(){
char c = 4;
c=c*200;
printf("%d\n",c);
return 0;
}
我想知道为什么输出会给出32.你能告诉我吗?我想要精确的计算。
答案 0 :(得分:2)
警告,提前啰嗦回答。编辑参考C标准,并对所提出的问题更清晰,更简洁。
为什么你有32岁的正确答案已被给了几次。使用模运算来解释数学是完全正确的,但如果您不熟悉编程,可能会让您更难直观地掌握。因此,除了现有的正确答案之外,还有一个可视化。
您的char是8位类型,因此它由一系列8个零和1组成。
查看二进制中的原始位,当无符号时(让我们将签名类型暂时保留,因为它只会混淆该点),变量“c”可以采用以下范围内的值:
00000000 -> 0
11111111 -> 255
现在,c * 200 = 800.这当然大于255.二进制800看起来像:
00000011 00100000
要在内存中表示这一点,您至少需要10位(请参见高位字节中的两个1)。另外,前导零没有明确需要存储,因为它们对数字没有影响。然而,下一个最大的数据类型将是16位,并且无论如何都更容易显示一致大小的位分组,所以就是这样。
由于char类型限制为8位且无法表示结果,因此需要进行转换。 ISO / IEC 9899:1999第6.3.1.3节说:
6.3.1.3有符号和无符号整数
1当整数类型的值转换为_Bool以外的另一个整数类型时,if 该值可以用新类型表示,不变。
2否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内。
3否则,新类型已签名且值无法在其中表示;无论是 结果是实现定义的或引发实现定义的信号。
因此,如果你的新类型是无符号的,那么遵循规则#2,如果我们从800减去一个超过新类型(256)的最大值,我们最终会在新类型的范围内以32结尾。这种行为也有可能有效地截断结果,因为你可以看到无法表示的较高位已被丢弃。
00100000 -> 32
现有的答案解释了使用模运算,其中800%256 = 32.这只是数学,它给出了除法运算的余数。当我们将800除以256时,得到3(因为256最多适合800次,最多三次)加上32的余数。这与在此处应用规则#2基本相同。
希望这能说明为什么会得到32的结果。但是,正如已经正确指出的那样,如果目标类型已签名,我们会查看规则#3,它表示行为是实现定义的。由于标准还表示您使用的普通字符类型可能是有符号或无符号的(并且这是实现定义的),因此您的特定情况是实现定义的。但是,在实际操作中,您通常会看到丢失较高位的相同行为,因此通常仍会获得32位。
稍微扩展一下,如果你有一个签名的8位目标类型,而你用c = c * 250代替运行你的代码,你会得到:
00000011 11101000 -> 1000
并且您可能会发现在转换为较小的签名类型后,结果同样被截断为:
11101000
对于大多数使用二进制补码的系统,有符号类型的解释为-24。事实上,当我在gcc上运行时会发生这种情况,但语言本身并不能保证这一点。