C 结构/结构值的内存分配

C 结构/结构值的内存分配,c,gcc,structure,C,Gcc,Structure,你能帮我理解为什么我的dataStruct结构的值不是它的一个成员的值吗?至于简单的结构 我用这行打印值: printf("dataStruct:..............0x%X\r\n", dataStruct); 结果是: dataStruct:..............0x22FE20 simpleDataStruct:........0xEFBE Addr simpleDataStruct: 0x22FE4A Size simpleDataStruct: 2 Addr

你能帮我理解为什么我的dataStruct结构的值不是它的一个成员的值吗?至于简单的结构

我用这行打印值:

printf("dataStruct:..............0x%X\r\n", dataStruct);
结果是:

dataStruct:..............0x22FE20
simpleDataStruct:........0xEFBE
Addr simpleDataStruct:   0x22FE4A
Size simpleDataStruct:   2

Addr localDataC:         0x22FE4D
Size localDataC:         1
Addr localDataD:         0x22FE4C
Size localDataD:         1
dataStruct:..............0x22FE20
dataStruct.a:            0xCA
dataStruct.b:            0x22FE4C
Addr dataStruct:         0x22FE30
Addr dataStruct.a:       0x22FE30
Addr dataStruct.b:       0x22FE38
Size dataStruct:         16
我使用GCC

我的代码是:

int main(void)
{
    typedef struct Main_SimpleStructData_s
    {
        unsigned char a;
        unsigned char b;
    }
    Main_SimpleStructData_t;

    typedef struct Main_StructuredData_s
    {
        unsigned char  a;
        unsigned char* b;
    }
    Main_StructuredData_t;

    unsigned char localDataA = 0xBE;
    unsigned char localDataB = 0xEF;
    unsigned char localDataC = 0xCA;
    unsigned char localDataD = 0xFE;

    Main_SimpleStructData_t  simpleDataStruct;
    Main_StructuredData_t    dataStruct;

    simpleDataStruct.a = localDataA;
    simpleDataStruct.b = localDataB;

    dataStruct.a    = localDataC;
    dataStruct.b    = &localDataD;

    printf("\r\n");
    printf("simpleDataStruct:........0x%X\r\n", simpleDataStruct);
    printf("Addr simpleDataStruct:   0x%X\r\n", &simpleDataStruct);
    printf("Size simpleDataStruct:   %u\r\n",   (unsigned)sizeof(simpleDataStruct));
    printf("\r\n");
    printf("Addr localDataC:         0x%X\r\n", &localDataC);
    printf("Size localDataC:         %u\r\n",   (unsigned)sizeof(localDataC));
    printf("Addr localDataD:         0x%X\r\n", &localDataD);
    printf("Size localDataD:         %u\r\n",   (unsigned)sizeof(localDataD));
    printf("dataStruct:..............0x%X\r\n", dataStruct);
    printf("dataStruct.a:            0x%X\r\n", dataStruct.a);
    printf("dataStruct.b:            0x%X\r\n", dataStruct.b);
    printf("Addr dataStruct:         0x%X\r\n", &dataStruct);
    printf("Addr dataStruct.a:       0x%X\r\n", &(dataStruct.a));
    printf("Addr dataStruct.b:       0x%X\r\n", &(dataStruct.b));
    printf("Size dataStruct:         %u\r\n",   (unsigned)sizeof(dataStruct));

    return (0);
}
结果是:

dataStruct:..............0x22FE20
simpleDataStruct:........0xEFBE
Addr simpleDataStruct:   0x22FE4A
Size simpleDataStruct:   2

Addr localDataC:         0x22FE4D
Size localDataC:         1
Addr localDataD:         0x22FE4C
Size localDataD:         1
dataStruct:..............0x22FE20
dataStruct.a:            0xCA
dataStruct.b:            0x22FE4C
Addr dataStruct:         0x22FE30
Addr dataStruct.a:       0x22FE30
Addr dataStruct.b:       0x22FE38
Size dataStruct:         16
提前谢谢。

转换采用无符号int参数。您错误地传递了一个struct Main_structuredatas,它不是一个无符号int,这是一种未定义的行为,因此我不知道为什么您希望看到结果是合理的

编辑:至于为什么主\u SimpleStructData \u t通过显示其成员来工作,答案仍然是它是未定义的行为,它可以做任何事情,包括正确的事情。这种情况的根本原因几乎可以肯定是:

printf试图读取一个无符号int参数,因为当您说您传递了一个无符号int时,它不知道您实际传递了什么 小Main_SimpleStructData_t恰好作为参数传递,其方式与平台上的无符号int相同,printf最终读取其成员的值。 较大的Main_structuredata_t恰好以另一种方式作为参数传递,例如,在堆栈上而不是在寄存器中,printf读取一些随机值,因为该结构不在unsigned int参数所在的位置。
调用函数printf时,参数被推送到堆栈上

printf在打印堆栈中的值时弹出堆栈。堆栈不包含有关数据类型(即格式说明符的作业)的信息

格式说明符告诉printf在堆栈上传递的数据类型,然后知道这些参数的大小,否则无法知道

printf无法处理这样的用户定义结构,如果您指定格式说明符%x,它将尝试一些操作,但这是未定义的行为。您可以用&和或结构的成员写出结构的地址前缀,但不能写出结构本身


您可以使用自定义格式说明符编写自己的printf函数,该说明符在按值传递struct后在内部打印出成员,但现在还没有。搜索stdarg.h以获取更多信息

@EOF、@Ctx、@Anders和@Arkku:非常感谢您的帮助。我知道问题出在笔记本电脑和椅子之间;我很愚蠢,但现在我是个男人了:

总之,我不知道如何正确使用printf函数。GCC已经向我发布了警告,但我并没有看到这些

如果我的简单Main_SimpleStructData_t结构变得更复杂,行为是相同的:未定义

typedef struct Main_SimpleStructData_s
{
    unsigned char a;
    unsigned int  c;  // Add a little bit complication
    unsigned char b;
}
Main_SimpleStructData_t;
结果是:

simpleDataStruct:......0x22FE20  // Undefined behaviour also !
Addr simpleDataStruct: 0x22FE40
Size simpleDataStruct: 12

那是很多东西。当然不是所有相关的?将其缩减到最小值,并告诉我们对于每一行给出意外输出的内容,您认为输出应该是什么。将参数传递给printf的未定义行为,该参数与相应的转换说明符不匹配。如果启用警告,gcc可能会对此发出警告。使用%X printf,当参数将数据推送到堆栈上时,会从某个CPU寄存器获取要打印的值。这就是为什么从结构中看不到任何值。请注意,此解释取决于平台,其他平台上的观察结果可能会有所不同。您能帮助我理解为什么我的dataStruct结构的值不是它的一个成员的值吗?那个问题毫无意义。这就像问为什么你的车和它的一扇门不一样。结构不是简单的数据类型,它不能具有与简单数据类型相同的值。@JohnZwinck:Done。在许多常见的平台上,不仅从堆栈,而且从寄存器(即fp寄存器的浮点值)。@ctx yes true,只是试图说明一个点,没有关于这个论点的信息types@purJuS这仍然是未定义的行为,但在这种情况下,它碰巧做了一些合理的事情。可能是因为两个成员都是无符号字符,并且大小仅为2,并且它碰巧以与传递兼容的方式传递两个字符参数的结构。另一个结构有一个指针unsigned char*,这会导致在内部填充结构以正确对齐指针,大小为16,并且最终以不兼容的方式作为参数传递。但唯一重要的答案是,这是未定义的行为,您无法对此进行推理。当我打印simpleDataStruct结构时,结果是成员值:simpleDataStruct:……0xEFBE。我想理解为什么dataStruct的打印结果不是其成员中包含的值。@purJuS从另一个角度看,为什么simpleDataStruct显示其成员的值并不奇怪?将该结构打印为无符号整数也是st中未定义的行为
因此编译器可以自由地生成格式化硬盘的代码。仅仅因为一个未定义行为的例子做了你认为你能理解的事情,这并不意味着其他未定义行为的例子也需要做同样的事情。@purJuS另一方面,如果你真的想知道为什么在这个特殊的例子中会发生这种情况,你可以看看生成的汇编代码。我相信您会发现,平台的调用约定是这样的:两种结构的传递方式不同,可能是寄存器中的小结构和堆栈中的大结构,但printf相信您在这两种情况下都以传递无符号int的方式传递了无符号int,并尝试读取它。碰巧第一个结构是以同样的方式传递的,而第二个不是。更正:它不会变成未定义的行为。当你通过一个错误的论点时,这已经是一种未定义的行为,你只是看到了不同的结果。未定义意味着任何事情都有可能发生,包括它看起来工作正常的可能性。或者,它可以打印莎士比亚全集或格式化硬盘。@Arkku+1。谢谢,我只是想解释一下原因。开始时,我想检查一些结构的内存分配。我认为打印内存地址是表示内存映射的一个很好的解决方案。使用prints函数是一个错误。谢谢你的负面评论,有了这个世界就更好了!