假设我有两个结构:
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结构I只有不受严格别名规则影响的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);发布于 2019-08-24 15:45:49
合法的。根据memcpy手册: memcpy()函数将n个字节从内存区域src复制到内存区域dest。内存区域不能重叠。如果内存区域确实重叠,请使用memmove(3)。
所以它根本不关心类型。它只是按照你说的去做。因此,请谨慎使用它,如果您使用了some (A)而不是sizeof(b),您可能已经覆盖了堆栈上的其他一些变量。
发布于 2019-08-24 15:04:49
虽然这不是一个直接的答案,但可能会有所帮助。
如果您想要重叠的struct,可以使用union
typedef union
{
generic_t generic;
specific_t specific;
} combined_t;这就避免了转换的需要。但是,您需要非常小心,以确保您没有访问sth_else,如果它没有初始化。您需要数据和逻辑来确定设置了哪些union成员以及访问函数/宏。这正致力于在C中构建类继承。
在过去,我在C中构建了一个类似Java的异常处理机制(so try,catch,.)。这具有链接时异常“类”继承的特点。因此,编译后的库可以定义一个SomeException 'class',然后用户代码可以‘子类’这个异常,新的‘子类’异常仍然会被一个SomeException catch子句捕获。如果您需要停留在C中,那么您可以使用智能宏和一些精心选择的简单的C结构来做很多事情。
https://stackoverflow.com/questions/57639016
复制相似问题