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

时间:2015-07-22 11:55:11

标签: 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);
}

输出:

Char size: 1 
int16_t size: 2 
They are the same 
They are the same 
ffffffff 
ffffffff 
ffffffff 
ffffffff

为什么为charint16_t打印32位值,为什么可以对它们进行比较并认为是相同的?

3 个答案:

答案 0 :(得分:5)

它们是相同的,因为它们是-1的所有不同表示。

他们打印为32位'价值ff,因为您使用的是32位计算机并且使用了%d并且发生了默认参数促销(基本上,所有较小的内容都会被提升为{ {1}})。尝试使用int。 (那可能会让你%hx;除了使用ffff或屏蔽ff之外,我不知道如何获得unsigned char。 }:& 0xff。)

扩展"它们是相同的,因为它们是-1和#34;的所有不同表示形式:

printf("%x \n", array2[0] & 0xff)是带符号的16位类型。它可以包含-32768到+32767范围内的值 int16_t是8位类型,并且在您的计算机上它也显然已签名。因此它可以包含-128到+127范围内的值。

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

0xffff是十进制65535,这个值不能在char中表示。如果将0xffff分配给int16_t,则该位模式最终会被解释为65535,而不是-1。 (同样,如果你指定了0xfffe,那将被解释为65534,而不是-2。)

所以当你说

int16_t

基本就好像你说的那样

int16_t array1[] = {0xffff,0xffff,0xffff,0xffff};

当你说

int16_t array1[] = {-1,-1,-1,-1};

就好像你说的那样

char array2[] = {0xff,0xff,0xff,0xff};

这就是char array2[] = {-1,-1,-1,-1}; *array1 == *array2

的原因

此外,值得注意的是,由于array1[0] == array2[0]array1的类型,所有这些都非常重要。如果你改为说

array2

您会看到打印的不同值(uint16_t array3[] = {0xffff,0xffff,0xffff,0xffff}; unsigned char array4[] = {0xff,0xff,0xff,0xff}; ffff),ffarray3的值不会相同。

另一个答案说明" C在运行时没有类型信息"。在这种情况下,这是真的但有误导性。当编译器生成代码来处理来自array4array1array2array3的值时,它生成的代码(当然 )在运行时有意义!)将基于他们的类型。特别是,在生成代码以从array4array1(但 array2array3)中获取值时,编译器将使用指令在分配给较大类型的对象(例如32位)时执行符号扩展。这就是0xff和0xffff如何变成0xffffffff。

答案 1 :(得分:1)

由于C 在运行时中没有类型信息,并且使用普通%x进行打印,因此告诉printf您的指针指向{{1} }。糟糕的库函数只信任您...请参阅printf(3)中的长度修饰符,了解如何为unsigned int提供所需的信息。

答案 2 :(得分:1)

使用%x打印负值会导致undefined behaviour,因此您不应该假设您所看到的内容有任何明智之处。

char的正确格式说明符为%hhdint16_t的格式说明符为"%" PRId16。您需要#include <inttypes.h>才能获得后一个宏。

由于默认参数促销,将%dcharint16_t 1 一起使用也是正确的。如果您将代码更改为使用%d而不是%x,则它将不再显示未定义的行为,并且结果将有意义。

1 C标准实际上并没有这么说,但是假设这是作者的意图。