3

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

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

谁能解释一下为什么 o/p 快到 35 了?我目前正在使用 GCC 32 位编译器。

4

3 回答 3

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,您可能有兴趣阅读以下文档摘录:

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

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

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

于 2013-06-23T03:34:02.830 回答
3

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

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

291 % 256 = 35

291 & 0xFF = 35

一个 8 位字符可以包含 -128 到 127 或 0 到 255 的值,这取决于它是有符号的还是无符号的。

于 2013-06-23T03:34:41.037 回答
3

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

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

这实际上是用2 的补码系统表示 char 的方式:

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

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

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

但在这里,这个问题是无关紧要的。我们正在谈论模数,因为只考虑最后八位(当内存中只有八位可用时,另一个将存储在哪里?)。

291 = % 1 0010 0011

%表示二进制表示)

它只保留% 0010 0011which equals35和 which 将被视为完全相同,无论您是否签名。

于 2013-06-23T03:35:06.977 回答