这个C代码有什么问题?

我的源代码:

#include <stdio.h> int main() { char myArray[150]; int n = sizeof(myArray); for(int i = 0; i < n; i++) { myArray[i] = i + 1; printf("%d\n", myArray[i]); } return 0; } 

我使用的是Ubuntu 14和gcc来编译它,它打印出来的是:

 1 2 3 ... 125 126 127 -128 -127 -126 -125 ... 

为什么不计算到150?

看来你的编译器默认认为类型char类型signed char 。 在这种情况下, CHAR_MIN等于SCHAR_MIN ,而等于-128CHAR_MAX等于SCHAR_MAX ,又等于127 (参见标题<limits.h>

根据C标准(6.2.5类型)

三种类型的char,signed char和unsigned char被统称为字符类型。 实现应该定义char与signed char或unsigned char具有相同的范围,表示和行为

对于签名类型,一个位用作符号位。 因此,对于类型signed char ,最大值对应于以十六进制表示法的以下表示形式

 0x7F 

等于127.最高有效位是有符号位,等于0。

对于负值,有符号位设置为1,例如-128表示为

 0x80 

在你的程序中,存储在字符中的值达到正的最大值0x7F ,并增加到等于0x80 ,十进制表示等于-128

如果您希望程序执行的结果不依赖于编译器设置,则应明确使用类型unsigned char而不是char

或者在printf语句中,您可以明确地将类型char为键入unsigned char 。 例如

 printf("%d\n", ( unsigned char )myArray[i]); 

或者比较结果,你可以写在循环中

 printf("%d %d\n", myArray[i], ( unsigned char )myArray[i]); 

char int值的范围可以从0到255或-127到127,具体取决于实现。 因此,一旦在你的情况下值达到127,它溢出,你得到负值作为输出。

一个普通char的签名是实现定义的。

在你的情况下,一个char是一个有signed char ,它可以将范围的值保存为-128到+127。

当你增加i的价值超过极限signed char可以容纳并试图分配给myArray[i]你正在面对一个实现定义的行为。

引用C11第6.3.1.4章,

  1. 否则,新的类型被signed并且值不能被表示; 结果是实现定义的或实现定义的信号被引发。

因为char是一个带符号的字节 。 这意味着它的值范围是-128 – > 127。

编辑由于所有下面的评论暗示这是错误的/不是问题/签字/什么不…

运行这个代码:

 char a, b; unsigned char c, d; int si, ui, t; t = 200; a = b = t; c = d = t; si = a + b; ui = c + d; printf("Signed:%d | Unsigned:%d", si, ui); 

打印:签名:-112 | 无符号:400
试试看吧

原因是一样的。 ab是带符号的字符(大小为字节的签名变量 – 8位)。 cd是无符号的。 将200分配给已签名的变量溢出并获得值-56。 在记忆中, ab, c & d都具有相同的值,但是当使用他们的类型“signdness”时,这个值就是如何使用的,在这种情况下,它会产生很大的差别。

关于标准的说明

已经注意到(在对这个答案的评论以及其他答案中)标准没有要求字符被签名。 那是真实的。 然而,在OP提供的情况下,以及上面的代码,char被签名。