符合旧"struct hack"(?)的变体

13 c c89

我相信我已经找到了一种方法来实现便携式C89中众所周知的"struct hack".我很好奇这是否真的严格符合C89.

主要思想是:我分配足够大的内存来保存初始结构和数组元素.确切的大小是(K + N) * sizeof(array_base_type),K选择的位置是K * sizeof(array_base_type) >= sizeof(the_struct)N数组元素的数量.

首先,我取消引用malloc()返回存储的指针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;
Run Code Online (Sandbox Code Playgroud)

我主要担心的是最后两个赋值(使用frame指向Header的指针和指向Value的指针)可能违反严格的别名规则.但是,我不会将dereference hdr作为指向Value的指针 - 它只是frame为了访问value数组的第一个元素而执行的指针算术,所以我不能使用不同类型的指针有效地访问同一个对象.

那么,这种方法是否比经典的结构黑客(官方认为是UB)更好,还是UB呢?

tor*_*rek 5

"显而易见"(嗯......不是很明显,但无论如何都是想到的:-))导致这种情况破坏的方法是使用矢量化编译器,以某种方式决定加载,比如64 Header秒进入从42舍入到64 +区域中的矢量寄存器在hdr它来自malloc它总是分配足够的向量化.将向量寄存器存储回存储器可能会覆盖其中一个Value.

我认为这个矢量化编译器可以指向标准(好吧,如果编译器有手指......)并声称一致性.

但实际上,我希望这段代码能够正常运行.如果您遇到矢量化编译器,请添加更多空间(使用可插入最小值的机器相关宏进行舍入)并充电.:-)