如何在C中转储任意结构?

时间:2011-07-14 01:25:12

标签: c struct dump

我不知道要走哪个方向,也许反射会有所帮助?

4 个答案:

答案 0 :(得分:3)

这是一个十六进制转储,尽可能通用:

struct Foo x;

unsigned int i;
const unsigned char * const px = (unsigned char*)&x;

for (i = 0; i < sizeof(x); ++i) printf("%02X ", px[i]);

请注意,其结果完全是实现定义的;可能会有大量的填充,你不会知道任何印刷值是什么意思。 (他们中的大多数可能只是指向其他部分空间的指针。)

正如Etienne所说,C是一种静态类型语言,没有反射,所以你 知道Foo的声明,以便解释{{1}的内容}。

答案 1 :(得分:3)

@Kerrek SB的答案非常好,我只是在使用void指针的函数中发布如何使用它。

int dump(void *myStruct, long size)
{
    unsigned int i;
    const unsigned char * const px = (unsigned char*)myStruct;
    for (i = 0; i < size; ++i) {
        if( i % (sizeof(int) * 8) == 0){
            printf("\n%08X ", i);
        }
        else if( i % 4 == 0){
            printf(" ");
        }
        printf("%02X", px[i]);
    }

    printf("\n\n");
    return 0;
}

int main(int argc, char const *argv[])
{
    OneStruct data1, data2;

    dump(&data1, sizeof(OneStruct));

    dump(&data2, sizeof(OneStruct));

    return 0;
}

答案 2 :(得分:2)

一旦获得文件,您想对文件做什么?如果稍后将再次阅读,请使用freadfwrite,例如

struct foo * bar;
fwrite(bar,sizeof(*bar),1,stdout);

...

fread(bar,sizeof(*bar),1,stdin);

这将提供依赖于您的编译器/平台的二进制输出,只要它们保持不变就应该没问题。从那里你也可以将文件提供给十六进制阅读器等,但你需要知道结构的布局,以便用它做任何有用的事情。

答案 3 :(得分:2)

如果您使用的是Clang 8或更高版本,现在可以使用内置的编译器功能{​​{1}}来转储结构。它使用编译时自然可用的信息来生成漂亮地打印结构的代码。

演示该功能的示例代码:

dumpstruct.c:

__builtin_dump_struct

示例编译运行:

#include <stdio.h>

struct nested {
    int aa;
};

struct dumpme {
    int a;
    int b;
    struct nested n;
};

int main(void) {
    struct nested n;
    n.aa = 12;
    struct dumpme d;
    d.a = 1;
    d.b = 2;
    d.n = n;
    __builtin_dump_struct(&d, &printf);
    return 0;
}

如果您未使用Clang> = 8,但正在使用GCC,则切换起来非常容易。只需安装clang-8或clang-9软件包,并将$ clang dumpstruct.c -o dumpstruct $ ./dumpstruct struct dumpme { int a : 1 int b : 2 struct nested n : struct nested { int aa : 12 } } 的调用替换为gcc