内部结构中的短变量转储不合适

时间:2015-11-17 06:13:50

标签: c linux gcc

以下是代码段

socc.cc:16:23: warning: format ‘%s’ expects argument of type ‘char*’, but argument 2 has type ‘MyClass’ [-Wformat=]
     printf("%s\n", obj); // Crash

输出:

#include <stdio.h>

struct container {
    int myint;
    long mylong;
    short myshort;
}__attribute__((packed));

int main()
{
    struct container con = {.myint = 0x12345678,
        .mylong = 0x12345678,
        .myshort = 0xABCD};
    int i;
    char *ptr = (char *)&con;
    for (i = 0; i < 10; i++) {
        printf("%x ", *ptr);
        ++ptr;
    }
    printf("\n");
    return 0;
}

为什么短变量值是78 56 34 12 78 56 34 12 ffffffcd ffffffab ffffffcd而不是ffffffabcd? 代码有什么问题吗?

2 个答案:

答案 0 :(得分:3)

制作ptr unsigned char *而不是char *。您的循环限制也应为sizeof(con),而不是10。

答案 1 :(得分:0)

char类型不适合存储整数值,因为它具有实现定义的签名。这意味着它与任何其他整数类型不同,可能是有符号或无符号的,具体取决于编译器。在您的情况下,它是有符号的,因此任何大于0x7F的原始字节值都将被视为负数。

如果这样的char变量在某个时刻被提升为int,它将保留负值,0xCD变为0xFFFFFFCD等。

printf和所有其他变量参数列表函数总是根据一个名为&#34;默认参数promotion&#34;的奇怪规则来提升传递给它的参数。所有小整数类型(例如charshort等)都会提升为int,所有float都会提升为double

在您的情况下,char被提升为int,并保留了该符号。为了避免这样的问题,除了存储字符外,永远不要使用char。相反,这样做:

#include <stdint.h>

uint8_t* ptr = (uint8_t*)&con;