C 摆脱IAR编译警告Pa039&引用;未对齐结构件地址的使用“;

C 摆脱IAR编译警告Pa039&引用;未对齐结构件地址的使用“;,c,pointers,compiler-errors,iar,C,Pointers,Compiler Errors,Iar,ARM的IAR编译器 我有一个使用 #pragma pack(push, 4) typedef struct { int a; double b; } my_t; #pragma pack(pop) 我想获取一个字段的地址,然后转换成一个char* my_t d; char * p = (char *)(&(d.b)); 我是否可以在不使用杂注禁用警告的情况下实现此无警告功能?因为双精度通常比int大,而且由于结构已打包,因此当较小的字段首先出现时,字段b未正

ARM的IAR编译器

我有一个使用

 #pragma pack(push, 4)
 typedef struct {
    int a;
    double b;
 } my_t;
 #pragma pack(pop)
我想获取一个字段的地址,然后转换成一个
char*

my_t d;
char * p = (char *)(&(d.b));

我是否可以在不使用杂注禁用警告的情况下实现此无警告功能?

因为双精度通常比int大,而且由于结构已打包,因此当较小的字段首先出现时,字段
b
未正确对齐

首先放置较大的字段,两个字段应正确对齐:

 typedef struct {
    double b;
    int a;
 } my_t;

就我个人而言,我会使用pragmas关闭这段代码的警告,如下例所示

char *g(void)
{
#pragma diag_suppress=Pa039
  return (char *)(&d.b);
#pragma diag_default=Pa039
}
如果这不是一个选项,可以在
my\u t
中找到
b
的偏移量,并将其添加到
d

char *f(void)
{
  return (char *)&d + offsetof(my_t, b);
}

首先:您应该确保数据类型内部的双变量按4字节对齐,您的代码是正确的

 #pragma pack(push, 4)
 typedef struct {
    int a;
    double b;
 } my_t;
 #pragma pack(pop)
其次:您的变量地址应该位于对应的位置

#pragma data_alignment = 4 
my_t d;
char * p = (char *)(&(d.b));

不幸的是,交换成员不起作用<由于
pack
的原因,code>double仍将超出其正常对齐范围。编译器似乎考虑到
my\u t
可能会在数组中使用,即使这里的情况并非如此。使用压缩结构的主要原因是作为“模板”来解释来自另一个源的数据。例如,通信协议。因此,交换订单并不总是一种选择。对我来说,这似乎是一个错误的警报。编译器似乎不够复杂,无法看到这种特殊情况。我建议您禁用警告,并在完成后恢复它。@user694733是的,我想以整洁的便携方式执行此操作。
的可移植性已经有点过时了。如果希望序列化可移植,那么最好完全避免使用结构。手动将每个成员转换为字节数组,或使用位移位将其转换回字节数组。这也将解决endianness问题。我认为offsetof是一个实际的宏。如果是这样,那么它也将生成警告。我从兔子洞开始,但我需要typeof(),可移植性成了一个问题。不幸的是,我也需要它的可移植性,所以我想包装pragmas,结果总共有六个。@WilliamJBagshaw因为offsetof正是为这类事情而设计的,它在编译器中使用内部技巧来避免警告。我的两个例子都给出了iccarm 8.30中的干净编译。@WilliamJBagshaw offsetof版本也在gcc(Arm嵌入式处理器7-2017-q4-major)和armclang(Arm编译器6.7)中编译干净。这很简单。如果该字段适当对齐,则不会出现警告。问题是当字段由于某种原因没有适当对齐时,如何避免警告。这不是小事,是一个典型的错误。许多人认为数据打包和数据对齐是一回事。关键字为“#pragma data_alignment=4”`您可以使用压缩结构,但此结构可以位于0x2000001地址上。例如,编译器可以使用VLDR指令从结构字段加载值,但该指令的地址值必须是4的倍数!因此,使用#pragma data_alignment=4将确保正确定位并消除警告