以下代码工作正常,但是我想知道这是否有效使用 void* 与任何其他指针兼容的规则
#include <stdio.h>
typedef struct {
int foo;
} SomeStruct_t;
typedef void(*SomeFunction_t)(void* ptr);
void bar(SomeStruct_t* str) {
printf("%d\n", str->foo);
}
void teddy(void* anyPtr) {
SomeStruct_t* str = (SomeStruct_t*)anyPtr;
printf("%d\n", str->foo);
}
int main()
{
SomeFunction_t functPtr = (SomeFunction_t)bar;
SomeStruct_t data = {.foo = 33};
functPtr(&data);
functPtr = teddy;
functPtr(&data);
return 0;
}
问题是,我应该使用 bar
还是 teddy
变体?我更喜欢 bar
,但我不确定在某些极端情况下这是否会导致难以检测的问题。
答案 0 :(得分:5)
这是无效的:
SomeFunction_t functPtr = (SomeFunction_t)bar;
因为您将 void (*)(SomeStruct_t*)
类型的函数指针封装到 void (*)(void*)
类型,然后通过转换类型调用它。函数指针类型不兼容,因为参数不兼容。这会触发 undefined behavior。
虽然 SomeStruct_t *
可以转换为 void *
,但这种转换不会发生,因为强制转换的函数指针阻止了它。不能保证 SomeStruct_t *
和 void *
具有相同的表示形式。
使用与函数指针类型匹配的函数teddy
是安全的。此外,您无需在函数内将参数强制转换为 SomeStruct_t *
,因为在大多数情况下,与 void *
之间的转换不需要。