【发布时间】:2022-07-27 23:27:47
【问题描述】:
假设我有两个结构:object 和 widget:
struct object {
int field;
void *pointer;
};
struct widget {
int field;
void *pointer;
};
还有一个功能:
void consume(struct object *obj)
{
printf("(%i, %p)\n", obj->field, obj->pointer);
}
我知道,如果我尝试去做:
struct widget wgt = {3, NULL};
consume(&wgt);
我会违反strict aliasing rule,因此会有未定义的行为。
据我了解,未定义的行为是由于编译器可能以不同方式对齐结构字段:也就是说,填充字段以与地址边界对齐(但永远不会更改字段顺序,因为顺序保证是受到标准的尊重)。
但是如果这两个结构是packed 呢?它们会有相同的内存布局吗?或者,换句话说,上面的consume() 是否仍然有未定义的行为(尽管有持续的编译器警告)?
注意:我使用struct __attribute__((__packed__)) object { ... }; 进行打包(GCC)。
【问题讨论】:
-
packed根本不是 C 标准的一部分,因此您需要查看 GCC 文档(如果有)。 -
" .. 未定义的行为是由于编译器可能以不同方式对齐结构字段这一事实造成的”--> 我会说 UB 来自对一种数据类型对象的更改假设其他数据类型不变。 - 不是布局问题。 Zakk 代码试图避免什么问题?
-
鉴于结构声明和单独编译的工作方式,相同的结构必须相同,但这与语言保证不同。 (您要在此处添加语言-律师标签吗?)
-
@chux-ReinstateMonica 如果我没听错,您的意思是添加/删除/修改某些
object的字段吗? -
TL;DR:即使没有打包也可以,因为结构是相同的。它可能在技术上违反了标准中的某些条款,但它是“安全”的。但是,我从名称
object和widget推断您正在尝试做一个“通用”?这是我的一个可能有帮助的答案:Writing a 'generic' struct-print method in C