Char和int16数组元素都显示为32位十六进制?

The*_*eer 1 c variadic-functions integer-promotion

在下面的示例中:

int main(int argc, char *argv[])
{
    int16_t array1[] = {0xffff,0xffff,0xffff,0xffff};
    char array2[] = {0xff,0xff,0xff,0xff};
    printf("Char size: %d \nint16_t size: %d \n", sizeof(char), sizeof(int16_t));

    if (*array1 == *array2)
        printf("They are the same \n");
    if (array1[0] == array2[0])
        printf("They are the same \n");

    printf("%x \n", array1[0]);
    printf("%x \n", *array1);

    printf("%x \n", array2[0]);
    printf("%x \n", *array2);
}
Run Code Online (Sandbox Code Playgroud)

输出:

Char size: 1 
int16_t size: 2 
They are the same 
They are the same 
ffffffff 
ffffffff 
ffffffff 
ffffffff
Run Code Online (Sandbox Code Playgroud)

32位值为什么印刷两种charint16_t,为什么他们能进行比较和被认为是一样的吗?

Ste*_*mit 5

它们是相同的,因为它们都是-1的不同表示.

它们打印为32位,ff因为你在32位机器上使用%d并且使用了默认参数促销(基本上,所有小的都被提升到int).尝试使用%hx.(那可能会得到你ffff;我不知道ff除了通过使用unsigned char或掩盖以外的方式来到这里& 0xff:printf("%x \n", array2[0] & 0xff).)


扩展"它们是相同的,因为它们都是-1的不同表示":

int16_t是一个带符号的16位类型.它可以包含-32768到+32767范围内的值.
char是一个8位类型,并在您的机器上显然也签名.因此它可以包含-128到+127范围内的值.

0xff是十进制255,这是一个无法在signed char中表示的值.如果将0xff分配给有符号的char,则该位模式最终会被解释为255,而不是-1.(同样,如果你指定了0xfe,那么它将被解释为254,而不是-2.)

0xffff是十进制65535,这是一个无法用a表示的值int16_t.如果将0xffff分配给a int16_t,则该位模式最终会被解释为65535,而不是-1.(同样,如果你指定了0xfffe,那么它将被解释为65534,而不是-2.)

所以,当你说

int16_t array1[] = {0xffff,0xffff,0xffff,0xffff};
Run Code Online (Sandbox Code Playgroud)

这基本上就像你说的那样

int16_t array1[] = {-1,-1,-1,-1};
Run Code Online (Sandbox Code Playgroud)

而当你说

char array2[] = {0xff,0xff,0xff,0xff};
Run Code Online (Sandbox Code Playgroud)

就像你说的那样

char array2[] = {-1,-1,-1,-1};
Run Code Online (Sandbox Code Playgroud)

所以这就是原因*array1 == *array2,而且array1[0] == array2[0].


此外,值得注意的是,所有这一切都是因为类型非常多array1array2.如果你反而说

uint16_t array3[] = {0xffff,0xffff,0xffff,0xffff};
unsigned char array4[] = {0xff,0xff,0xff,0xff};
Run Code Online (Sandbox Code Playgroud)

您会看到打印(ffffff)的不同值,以及来自array3array4不会比较的值.

另一个答案说"在运行时C中没有类型信息".这是真的,但在这种情况下会产生误导.当编译器生成代码,以从操作值array1,array2,array3,和array4,它生成的代码(这当然在运行时显著!)将根据其类型.尤其是,生成代码时,从获取的值array1array2(但 array3array4),编译器将使用哪个执行指令符号扩展分配给更大的类型(例如,32位)的对象时.这就是0xff和0xffff如何变成0xffffffff.