函数指针中 void* 参数的自动转换

时间:2021-04-08 14:33:13

标签: c

以下代码工作正常,但是我想知道这是否有效使用 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,但我不确定在某些极端情况下这是否会导致难以检测的问题。

1 个答案:

答案 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 * 之间的转换不需要。

相关问题