[英]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.