我相信我已经找到了一种方法来实现类似便携式 C89 中著名的“struct hack”之类的东西。我很好奇这是否真的严格符合 C89。
主要思想是:我分配足够大的内存来保存初始结构和数组的元素。确切的大小是(K + N) * sizeof(array_base_type)
,K
选择其中K * sizeof(array_base_type) >= sizeof(the_struct)
并且N
是数组元素的数量。
首先,我取消引用malloc()
返回到 store的指针the_struct
,然后我使用指针算术来获得指向结构后面数组开头的指针。
一行代码价值超过一千字,所以这里是一个最小的实现:
typedef struct Header {
size_t length;
/* other members follow */
} Header;
typedef struct Value {
int type;
union {
int intval;
double fltval;
} v;
} Value;
/* round up to nearest multiple of sizeof(Value) so that a Header struct fits in */
size_t n_hdr = (sizeof(Header) + sizeof(Value) - 1) / sizeof(Value);
size_t n_arr = 42; /* arbitrary array size here */
void *frame = malloc((n_hdr + n_arr) * sizeof(Value));
if (!frame)
return NULL;
Header *hdr = frame;
Value *stack_bottom = (Value *)frame + n_hdr;
我主要担心的是最后两个赋值(frame
同时用作指向 Header 的指针和指向 Value 的指针)可能违反严格的别名规则。但是,我不会将取消引用hdr
作为指向 Value 的指针——它只是frame
为了访问 value 数组的第一个元素而执行的指针算术,所以我没有使用不同类型的指针有效地访问同一个对象。
那么,这种方法是否比经典的 struct hack(已被官方认定为 UB)更好,还是它也是 UB?