Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言的输出是什么?_C_Output - Fatal编程技术网

C语言的输出是什么?

C语言的输出是什么?,c,output,C,Output,我很难找到这段代码的输出。请帮我找出以下输出段的输出 #include<stdio.h> int main(){ char c = 4; c=c*200; printf("%d\n",c); return 0; } #包括 int main(){ 字符c=4; c=c*200; printf(“%d\n”,c); 返回0; } 我想知道为什么输出是32。你能告诉我吗?我要精确的计算。警告,前面有冗长的答案。编辑以参考C标准,并就所提出的问题更清

我很难找到这段代码的输出。请帮我找出以下输出段的输出

#include<stdio.h>

int main(){
    char c = 4;
    c=c*200;
    printf("%d\n",c);
    return 0;
}
#包括
int main(){
字符c=4;
c=c*200;
printf(“%d\n”,c);
返回0;
}


我想知道为什么输出是32。你能告诉我吗?我要精确的计算。

警告,前面有冗长的答案。编辑以参考C标准,并就所提出的问题更清晰、更简洁

关于你为什么有32个的正确答案已经给出了好几次。使用模块化算法解释数学是完全正确的,但如果您是编程新手,可能会使您更难直观地理解。因此,除了现有的正确答案之外,这里还有一个可视化

您的字符是8位类型,因此它由一系列8个0和1组成

查看二进制中的原始位,当无符号时(让我们暂时将有符号类型排除在外,因为它只会混淆点),变量“c”的值可以在以下范围内:

00000000 -> 0
11111111 -> 255
现在,c*200=800。这当然大于255。在二进制文件中,800看起来像:

00000011 00100000
要在内存中表示这一点,您至少需要10位(请参阅上面字节中的两个1)。另外,前导零不需要显式存储,因为它们对数字没有影响。然而,下一个最大的数据类型将是16位,而且更容易显示大小一致的位分组,所以它就存在了

由于字符类型限制为8位,并且不能表示结果,因此需要进行转换。ISO/IEC 9899:1999第6.3.1.3节规定:

6.3.1.3有符号和无符号整数

1当整数类型的值转换为除_Bool以外的其他整数类型时,如果 该值可以由新类型表示,但保持不变

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

对于大多数使用2的补码的系统,在有符号类型中被解释为-24。事实上,当我在gcc上运行它时会发生这种情况,但语言本身也不能保证这一点。

800%256=32。这是一种模运算。
800%256=32
assign to char会截断结果。char在-128和+128之间,每次通过其中一个范围时,您将转到另一端,执行剩余值的六倍-32。在计算完成之前,操作数将提升为
int
。如果使用
无符号字符
,则随后的截断定义良好,但如果
有符号字符
则溢出行为未定义(可能是实现定义的)。
char
是有符号的还是无符号的取决于实现,可以是其中之一。只有@WeatherVane的评论是完全正确的。我还应该指出,在处理数字时,您可能希望远离char之类的类型。有一些C标准数据类型不仅在大小上是显式的,而且在可能具有不同自然字号的平台上维护它们。uint8_t、uint16_t和uint32_t(以及它们的签名等价物)如果可用,则非常有用。几天前,我调试了一个单元测试,其中包括一个MD5(来自一个无名的提供商),但在我们的构建服务器上测试失败,因为他们使用的类型在64位Ubuntu上的行为不同。有符号整数溢出没有任何定义的行为。任何事情都有可能发生。代码可以打印,例如
800
。你不知道你的编译器。在你被烧伤之前别装了。哎哟,我想我刚才是这么做的:)。你是完全正确的。当然,这种行为不能保证,也不能依赖。我只希望进一步解释信息是如何存储的,因为这似乎是OP问题的根源。虽然我的咖啡和:F用完了,但这里确实没有带符号的整数溢出,因为数学发生在
int
s中,它总是适合800:D