这个C代码有什么问题?

这个C代码有什么问题?,c,ubuntu,gcc,C,Ubuntu,Gcc,我的源代码: #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; } 为什么它不直接计数到150呢?因为char是一

我的源代码:

#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;
}

为什么它不直接计数到150呢?

因为
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

原因是一样的
a
b
是有符号字符(大小为字节-8位的有符号变量)<代码>c和
d
未签名。将200赋值给有符号变量溢出,它们得到的值为-56。在内存中,
a
b,
c
&
d`都具有相同的值,但在使用时,它们的类型“signedness”指示如何使用该值,在这种情况下会产生很大的差异

关于标准的说明
已经注意到(在对本答案以及其他答案的评论中)该标准并未要求签署char。这是真的。但是,在OP提出的情况下,以及上面的代码中,char是有符号的。

普通的
char
的有符号性是由实现定义的

在您的例子中,
char
是一个
signed char
,它可以保存范围为-128到+127的值

当您将
i
的值增加到超出
signed char
所能容纳的限制,并试图将其分配给
myArray[i]
时,您将面临一个实现定义的行为

引用第§6.3.1.4章中的
C11

  • 否则,新类型为带符号的,且无法在其中表示值;要么结果是实现定义的,要么引发实现定义的信号

  • int
    字符的值可以在0到255或-127到127之间变化,具体取决于实现。
    因此,在您的例子中,一旦值达到127,它就会溢出,并且您会得到负值作为输出。

    在默认情况下,您的编译器将类型
    char
    视为与类型
    有符号char
    类似。在这种情况下,
    CHAR_MIN
    等于
    SCHAR_MIN
    ,反过来等于
    -128
    CHAR_MAX
    等于
    SCHAR_MAX
    ,反过来等于
    127
    (参见页眉

    根据C标准(6.2.5类型)

    15 char、signed char和unsigned char这三种类型是 统称为字符类型。实施应: 定义char,使其具有与相同的范围、表示形式和行为 有符号字符或无符号字符

    对于有符号类型,一位用作符号位。因此,对于类型
    有符号字符
    ,最大值对应于以下十六进制表示法

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

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

    0x80
    
    在您的程序中,存储在字符中的值达到其正最大值
    0x7F
    并增加后,它将变为等于
    0x80
    ,在十进制表示法中等于
    -128

    如果希望程序执行结果不依赖于编译器设置,则应显式使用type
    unsigned char
    而不是
    char

    或者在printf语句中,可以显式地将type
    char
    强制转换为type
    unsigned char
    。比如说

    printf("%d\n", ( unsigned char )myArray[i]); 
    
    或者,为了比较结果,您可以在循环中写入

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

    你不觉得它停在127(2^7-1)是可疑的吗?同样令人不快的是,你使用的是
    int
    ,其中应该使用
    size\u t
    ,因为
    sizeof
    的计算结果就是这样的。另外,它至少应该是
    int main(void)
    @alk为什么
    int main()
    不正确?除了字符串之外,不要使用普通
    char
    类型。相反,使用
    uint8\u t
    @fuzzxl在一些独立系统上可能是正确的,但我对此表示怀疑。在大多数C版本中,这是不正确的。但是它在C++中是完美的。因为字符是有符号字节。错了,标准没有说明它是有符号的还是无符号的。你得到了3张赞成票,真让赞成票的人感到羞耻。
    字符是一个有符号的字节。
    你能引用点什么吗?@cnicutar-你对标准的看法是对的,我对发生的事情的看法是对的(
    myArray
    是一个有符号的字节数组…@Amit-Ummm.)。。我想没有,因为这是UB。所以,没有什么是可以保证的。@cnicutar只是为了澄清一下,
    char
    的签名性是实现定义的,签名类型的溢出是UB。对吗?先生,我不认为原因是编译器的问题。导致这种情况的是printf的格式说明符“%d”。这与作为数据类型的“char”无关。@vish4071您错了。当参数从char类型提升到int类型时,它的符号性被保留。更常见的是二的补码,从-128到127。也许这就是你的意思。应该注意的是,有符号整数溢出在C中是未定义的。
    printf("%d %d\n", myArray[i], ( unsigned char )myArray[i]);