提问人:tonyjosi 提问时间:8/17/2023 最后编辑:tonyjosi 更新时间:8/17/2023 访问量:83
arm-none-eabi-gcc:packed 属性导致对齐效率低下
arm-none-eabi-gcc: packed attribute causes inefficient alignment
问:
将选项添加到 arm-none-eabi-gcc combiler 时,它会发出以下警告:-Wpacked
警告:打包属性导致“结构字段名称”的对齐效率低下
例如
struct Struct_test
{
uint32_t ch1;
uint16_t ch2;
uint32_t ch3;
}
__attribute__( ( packed ) );
警告字段 ch1 和 ch2:
test.c:12:14: warning: packed attribute causes inefficient alignment for 'ch1' [-Wattributes]
12 | uint32_t ch1;
| ^~~
test.c:13:14: warning: packed attribute causes inefficient alignment for 'ch2' [-Wattributes]
13 | uint16_t ch2;
| ^~~
根据手册的意思是:当 packed 属性对结构布局没有影响时发出警告。但在这种情况下,packed 属性确实会对结构布局产生影响,因为它删除了 ch2 和 ch3 之间的填充,但仍然会引起警告。-Wpacked
编辑:尽管警告被列为与以下项相关联。如果未作为编译选项给出,则不会显示。-Wattributes
-Wpacked
答:
1赞
Simon Goater
8/17/2023
#1
我没有 ARM CPU 来测试它,但我想我看到了问题所在。我想如果你把你的结构改成
struct Struct_test
{
uint32_t ch1;
uint32_t ch3;
uint16_t ch2;
}
__attribute__((aligned(4)))
__attribute__( ( packed ) );
那么问题就会消失,除非你创建一个这些结构的数组。这些打包结构的数组将存在对齐问题,如果尝试取消引用元素,可能会导致未定义的行为。您必须注意如何访问具有对齐问题的打包结构中的数据。一种安全的方法是对局部变量进行 memcpy。
通常,以节省空间的方式排列结构元素是个好主意。执行此操作的一种简单方法是将元素按大小递增或递减的顺序排列。
评论
0赞
tonyjosi
8/17/2023
更改为建议的结构定义将不起作用,因为现在所有 3 个字段都已经字节对齐,并且会生成 3 个警告。此外,并非总是可以更改结构定义中字段的顺序,例如,在表示 IP 数据包的结构定义中,它应始终按该顺序符合标准 IP 数据包中的字段。
0赞
artless noise
8/17/2023
@tonyjosi 这似乎是将元素保留在线形中的“解决方案”。但是,几乎总是这样,将反序列化例程转换为另一个“解包”结构将产生更好的代码。编译器将插入各种体操来处理未对齐的数据。
0赞
Simon Goater
8/17/2023
@tonyjosi 是的,打包时它似乎对整个结构进行字节对齐,这似乎有点疯狂。如果添加对齐属性,警告是否会消失?我无法获得相同的警告......
0赞
tonyjosi
8/18/2023
@SimonGoater 即使使用对齐的属性,警告仍然存在。这是我使用的 ARM GCC 工具链: arm-none-eabi-gcc [(Atmel build: 508) 6.3.1 20170620 (release)
评论
-Wattributes
-Wpacked
-Wattributes
warning: packed attribute causes inefficient alignment for 'ch1' [-Wpacked]
-Wattributes
-Wpacked