繁体   English   中英

关于这个计划的输出的困惑

[英]Confusion about the output of this program

我是C编程新手,我目前正在学习数据类型修订章节。 在下面的程序中,我的o / p是36,但编译器显示o / p 35。

main( )
{
char ch = 291 ;
printf ( "\n%d %c", ch, ch ) ;
}

任何人都可以解释为什么o / p即将到来35? 我目前正在使用GCC 32位编译器。

您的系统显然具有8位char类型。 这意味着291太大而不适合 - 编译器将其模数减少256(2 8 )并最终得到35。

在这种情况下, Clang提供了一个很好的警告:

example.c:3:11: warning: implicit conversion from 'int' to 'char' changes value
      from 291 to 35 [-Wconstant-conversion]
char ch = 291 ;
     ~~   ^~~

您应该避免依赖此行为,因为它可能因实现而异。 C99和C11规范(第6.3.1.3节)说明有符号整数转换:

否则,新类型将被签名,并且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号。

由于您正在使用GCC,您可能有兴趣阅读文档中的这段摘录:

当该值无法在该类型的对象中表示时,将整数转换为有符号整数类型的结果或信号(C90 6.2.1.2,C99 6.3.1.3)

为了转换为宽度N的类型,该值以2 N为模减少到该类型的范围内; 没有信号被提出。

在那里你有对减少模256的完整解释。

因为char只能包含8位信息,而291需要的信息要多于要存储的信息。 然后它将丢弃较高位并仅保留变量中的值。

您可以通过按位和模块操作来模拟它:

291%256 = 35

291和0xFF = 35

8位字符可以包含-128到127或0到255的值,具体取决于其是有符号还是无符号。

你实际上是在溢出。 签名字符只能在8位字符系统(几乎无处不在)中从值-128到127(256值= 2 8 )。 所以我们选择一个实际的字符,其值等于291%256 = 35。

不要忘记第一个字符是0而不是1。

这里实际上是如何使用2的补码系统表示char:

unsigned
0 ------- 127 128 ------- 255

signed
0 ------- 127 -128 ------- -1

所以实际上signed char c1 = -128等于unsigned char c2 = 128

但这里这个问题无关紧要。 我们讨论的是模数,因为只考虑了最后8位(如果内存中只有8位可用,那么另一位会被存储?)。

291 = % 1 0010 0011

%表示二进制表示)

它只保留% 0010 0011等于35 ,并且无论你是否接受它都将被视为完全相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM