Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 对这个程序的输出感到困惑_C - Fatal编程技术网

C 对这个程序的输出感到困惑

C 对这个程序的输出感到困惑,c,C,我是C编程新手,目前正在学习数据类型修订章节。在下面 程序,我的o/p是36,但编译器显示o/p是35 main( ) { char ch = 291 ; printf ( "\n%d %c", ch, ch ) ; } 谁能给我解释一下为什么o/p要来?我目前正在使用GCC 32位编译器。您的系统显然具有8位字符类型。这意味着291太大,无法容纳-编译器将其减少为256(28)模,最终得到35 在这种情况下,它提供了一个很好的警告: example.c:3:11: warning: impl

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

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

谁能给我解释一下为什么o/p要来?我目前正在使用GCC 32位编译器。

您的系统显然具有8位
字符类型。这意味着
291
太大,无法容纳-编译器将其减少为256(28)模,最终得到35

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

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的类型,该值被减少到模2N,以在该类型的范围内;没有发出任何信号


在这里,您有了对模256的约化的完整解释。

因为一个
字符只能包含8位信息,而291需要存储的信息比这还要多。然后,它将丢弃较高的位,只保留变量中适合的位

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

291%256=35

291&0xFF=35


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

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

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

以下是字符的实际表示方式:

所以实际上一个
有符号字符c1=-128
等于一个
无符号字符c2=128

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

%
表示二进制表示)


它只保留
%0010 0011
,该值等于
35
,并且无论您是否对其进行签名,该值都将被视为完全相同。

您应该使用
gcc-Wall-g
0..255进行编译,除非对普通
char
进行签名,而该值通常为-128..+127。谢谢您的回答。但你为什么在这里取模数?我的理解是,有符号字符的范围从-128到127。在上面的代码中有一个溢出。因此,根据我的理解,对于printf中的%c,将给出以下o/p 291-127=164-128=36。因此,它必须给出o/p 36你是对的,我会编辑它,但由于模在127以下,
无符号字符
字符
的行为是相同的。不,你的演算错了,它实际上只是291-256=35,因为你的字符包含8位。我的理解是,有符号字符的范围是-128到127。在上面的代码中有一个溢出。因此,根据我的理解,对于printf中的%c,将给出以下o/p 291-127=164-128=36。因此,它必须给出o/p 36。但是,正如您的示例所示,它显然没有给出o/p 36。您的编译器文档说明了什么?我不明白你为什么要先减去127,然后再减去128。但不管是无符号的还是有符号的,都不会改变任何东西。考虑到这一点,它更像是一个0->128,-127->1I的范围,我刚刚去为您查找了文档-我在上面的回答中添加了解释。谢谢您的回复。但为什么会在这里?我的理解是,有符号字符的范围从-128到127。在上面的代码中有一个溢出。因此,根据我的理解,对于printf中的%c,将给出以下o/p 291-127=164-128=36。因此,它必须给出o/p 36。正如我所说,这是一个模拟公式。溢出发生在二进制级别,没有解决任何算术问题。
unsigned
0 ------- 127 128 ------- 255

signed
0 ------- 127 -128 ------- -1
291 = % 1 0010 0011