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

时间:2013-06-23 03:30:38

标签: c

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

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

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

3 个答案:

答案 0 :(得分:8)

您的系统显然具有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,您可能有兴趣阅读the documentation中的摘录:

  

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

     

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

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

答案 1 :(得分:3)

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

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

291%256 = 35

291& 0xFF = 35

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

答案 2 :(得分:3)

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

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

实际上,实际上是如何使用2's complement system表示字符:

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的{​​{1}},并且无论您是否接受签名,都将被视为完全相同。