C 结构/结构值的内存分配
你能帮我理解为什么我的dataStruct结构的值不是它的一个成员的值吗?至于简单的结构 我用这行打印值: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
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函数是一个错误。谢谢你的负面评论,有了这个世界就更好了!