C:gcc隐式将signed char转换为unsigned char,反之亦然?

j0k*_*ker 9 c gcc types

我正在努力学习C,因为目前我已经陷入了数据类型.

看看这段代码:

#include <stdio.h>
#include <limits.h>

int main() {
    char a = 255;
    char b = -128;
    a = -128;
    b = 255;
    printf("size: %lu\n", sizeof(char));
    printf("min: %d\n", CHAR_MIN);
    printf("max: %d\n", CHAR_MAX);
}
Run Code Online (Sandbox Code Playgroud)

printf输出是:

size: 1
min: -128
max: 127
Run Code Online (Sandbox Code Playgroud)

怎么可能?char的大小是1 Byte,默认的char似乎是签名的(-128 ... 127).那么如何在不发出溢出警告的情况下分配值> 127(我在尝试分配-128或256时得到)?gcc会自动转换为unsigned char吗?然后,当我指定负值时,它会转换回来吗?它为什么这样做?我的意思是,所有这些隐含性都不会让它更容易理解.

编辑:

好吧,它没有转换任何东西:

char a = 255;
char b = 128;
printf("%d\n", a);    /* -1 */
printf("%d\n", b);    /* -128 */
Run Code Online (Sandbox Code Playgroud)

所以它从下往上开始计算.但为什么编译器没有给我一个警告?为什么会这样,当我尝试分配256?

pmg*_*pmg 8

参见C99标准中的 6.3.1.3/3

...新类型已签名且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号.

因此,如果您没有收到信号(如果您的程序没有停止),请阅读编译器的文档以了解它的作用.


gcc记录行为(在http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation中)

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

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