我是 C 编程新手,目前正在学习数据类型修订章节。在下面的程序中,我的 o/p 是 36,但编译器显示的是 o/p 35。
main( )
{
char ch = 291 ;
printf ( "\n%d %c", ch, ch ) ;
}
谁能解释一下为什么 o/p 快到 35 了?我目前正在使用 GCC 32 位编译器。
我是 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 的完整解释。
因为 achar
只能包含 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
所以实际上 asigned char c1 = -128
等于unsigned char c2 = 128
但在这里,这个问题是无关紧要的。我们正在谈论模数,因为只考虑最后八位(当内存中只有八位可用时,另一个将存储在哪里?)。
291 = % 1 0010 0011
(%
表示二进制表示)
它只保留% 0010 0011
which equals35
和 which 将被视为完全相同,无论您是否签名。