使用 memcpy() 进行结构复制是否合法?

Is struct copying with memcpy() legal?

假设我有两个结构:

typedef struct {
    uint64_t type;
    void(*dealloc)(void*);
} generic_t;

typedef struct {
    uint64_t type;
    void(*dealloc)(void*);
    void* sth_else;
} specific_t;

复制到更简单结构的常用方法是:

specific_t a = /* some code */;
generic_t b = *(generic_t*)&a;

但这是非法的,因为它违反了严格的别名规则。

但是,如果我 memcpy 结构我只有 void 个不受严格别名规则影响的指针:

extern void *memcpy(void *restrict dst, const void *restrict src, size_t n);

specific_t a = /* some code */;
generic_t b;
memcpy(&b, &a, sizeof(b));

像这样用 memcpy 复制结构是否合法?


一个示例用例是通用释放器:

void dealloc_any(void* some_specific_struct) {
    // Get the deallocator
    generic_t b;
    memcpy(&b, some_specific_struct, sizeof(b));

    // Call the deallocator with the struct to deallocate
    b.dealloc(some_specific_struct);
}

specific_t a = /* some code */;
dealloc_any(&a);

虽然这不是一个直接的答案,但它可能会有所帮助。

如果你想要重叠 structs,你可以使用 union:

typedef union
{
    generic_t  generic;
    specific_t specific;
} combined_t;

这避免了强制转换的需要。但是您需要非常小心,以确保在 sth_else 未初始化的情况下您不会访问它。您将需要数据和逻辑来确定 union 成员中的哪些成员已设置以及访问权限 functions/macros。这是为了在 C 中构建 class 继承。

过去我在 C 中构建了一个类似于 Java 的异常处理机制(所以 trycatch、...)。这具有 link-time 异常 'class' 继承。因此编译库可以定义一个 SomeException 'class',然后用户代码可以 'subclass' 这个异常,并且新的 'subclass' 异常仍然会被 SomeException 捕获捕捉子句。如果您需要留在 C 中,您可以使用智能宏和一些精心挑选的简单 C 结构来做很多事情。

合法。 根据memcpy手册:memcpy()函数将n个字节从内存区src复制到内存区d​​est。存储区不得重叠。如果内存区域重叠,请使用 memmove(3)。

所以它根本不关心类型。 它只是完全按照您的指示去做。 所以谨慎使用它,如果你使用 sizeof(a) 而不是 sizeof(b) 你可能已经覆盖了堆栈上的一些其他变量。