C 联合成员数据对齐
我在联盟中的数据对齐方面遇到了一些问题,我似乎无法解决。使用与下面类似的联合,联合的基址上似乎有一些数据偏移C 联合成员数据对齐,c,unions,C,Unions,我在联盟中的数据对齐方面遇到了一些问题,我似乎无法解决。使用与下面类似的联合,联合的基址上似乎有一些数据偏移 typedef union MyUnion { struct MyStruct { uint16_t val_1; uint8_t val_2; uint8_t val_3; }data; uint8_t data_array[4]; }MyUnion; 在某种程度上,我已经用数据填充了结构 my_un
typedef union MyUnion
{
struct MyStruct
{
uint16_t val_1;
uint8_t val_2;
uint8_t val_3;
}data;
uint8_t data_array[4];
}MyUnion;
在某种程度上,我已经用数据填充了结构
my_union.data.val_1 = 65535;
my_union.data.val_2 = 0;
my_union.data.val_3 = 0;
然后我尝试使用数组访问数据。我希望在数组的基址处看到的是val_1255的第一个字节。但是,当访问数组中的数据时,它似乎与结构的基偏移了1字节
printf("Bytes of struct: %#08x\n", my_union.data.val_1);
printf("Bytes of array: %#08x\n", my_array.data_array[0]);
无论我在上面输入什么值,结果都与此类似
Bytes of struct: 0x00ffff
Bytes of array: 0x0000ff
我最初认为,成员可能以某种方式被偏移,并且引用了不同的内存地址,但当我打印它们的地址时,它们是相同的
此外,如果我打印以下值,它们是相等的
printf("Bytes of struct: %#08x\n", my_union.data);
printf("Bytes of array: %#08x\n", *(my_array.data_array - 1) );
输出:
Bytes of struct: 0x00ffff
Bytes of array: 0x00ffff
我肯定我错过了一些简单的东西,但我现在还不明白。提前感谢您的帮助。这绝对是错误的:
printf("Bytes of array: %#08x\n", my_array.data_array);
您正在打印数组第一个元素的地址,而不是您感兴趣的内容
无论如何,打印指针应该使用%p
格式,所以一个好的编译器应该给你一个警告
要打印数组的内容,必须打印其中的每个元素。uint8\u t
(而不是unint8\u t
!)的正确格式说明符是宏PRIx8
试试这个
printf("Bytes of struct: %#08x\n", *(uint32_t*)&my_union.data);
printf("Bytes of array: %#08x\n", *(uint32_t*)my_union.data_array);
在小型endian计算机(Intel Core i7、Mac OS X 10.9.1 Mavericks、GCC 4.8.2)上运行以下程序:
#include <inttypes.h>
#include <stdio.h>
typedef union MyUnion
{
struct MyStruct
{
uint16_t val_1;
uint8_t val_2;
uint8_t val_3;
} data;
uint8_t data_array[4]; // NB: was unint8_t!!!
} MyUnion;
int main(void)
{
MyUnion my_union;
my_union.data.val_1 = 0xFEDC;
my_union.data.val_2 = 0xBA;
my_union.data.val_3 = 0x98;
printf("val_1 = 0x%.4" PRIX16 "; val_2 = 0x%.2" PRIX8 "; val_3 = 0x%.2" PRIX8 "\n",
my_union.data.val_1, my_union.data.val_2, my_union.data.val_3);
char const *pad = "";
for (size_t i = 0; i < sizeof(my_union.data_array); i++)
{
printf("%sarray[%zu] = 0x%.2" PRIX8, pad, i, my_union.data_array[i]);
pad = "; ";
}
putchar('\n');
return 0;
}
这正是我所期望的。在big-endian机器上,您会得到不同的输出(或多或少,除了Intel之外的任何东西)
您需要调整此代码(或非常类似的代码),以演示您发现的任何问题,并显示修改后的代码和实际输出,以及您对期望的内容和期望不同输出的原因的解释。您应该会遇到错误。发布一个sscce,而不是代码片段。您实际使用的工会与下面的工会有多相似?你真的能重现你在问题中表现出来的工会的问题吗?您能否显示编译的完整但最少的代码及其生成的输出,并确定运行它的编译器和平台?您选择的值对于诊断问题不是很好;您应该考虑分配(例如)0xFEDC到<代码> Valy1 ,也许是0xBA到<>代码> Valu2和0x89> <代码> Valy3。请参见MCTRE/MCVE@JonathanLeffler,这是完全不同的,结构包含一些奇怪的数据类型,即位字段结构,但联合体中结构的第一个成员是无符号短字符。我使用的是MingWGCC4.6.2。该平台是Altera公司的RISC软处理器,名为NIOSII。对示例中的值表示抱歉。我使用了一些可以单独跟踪字节的方法,它显示了上面的行为。数组数据总是从结构数据偏移一个字节。OK;你肯定有一个更复杂的问题。因此,您需要生成在您的环境中再现您的问题的最小代码-请参阅我的答案以获得可能的概要-然后显示该代码、实际输出、预期输出,以及解释您认为实际输出错误和预期输出正确的原因。RISC处理器是大端还是小端?我注意到您的评论“我使用了[values],其中我可以单独跟踪字节”是不准确的;您无法区分这两个0xFF字节,也无法区分这两个0x00字节。@JonathanLeffler抱歉,我的意思是调试时我没有将0xFF用于字节。我实际上使用了我可以看到的字节值。我基本上做了与您在环境中的示例相同的事情。我将很快发布这个示例。字节顺序是小端。谢谢。这正是我期望看到的。我也遍历了数组,得到了相同的字节偏移量。我也看到了你的其他评论。我会在那里答复的。谢谢
val_1 = 0xFEDC; val_2 = 0xBA; val_3 = 0x98
array[0] = 0xDC; array[1] = 0xFE; array[2] = 0xBA; array[3] = 0x98