C++-17 : cast function pointer to function with different argument pointer type

标签 c++ c++17 function-pointers

我有一个遗留的 C-API,它为异步操作提供回调。 由于该库需要许多编译器标志,充满了宏,并且 header 在包含时会生成大量警告,因此我决定为该库创建一个包装器来封装专有的 C 库。

但由于该库是异步的,因此它提供了回调函数。 问题是,回调需要一个指向结构的指针 (X_leg)。 但由于这个结构是旧 API 的一部分,我不想包含该结构, 我决定创建一个具有相同布局 X_wrp 的结构。 在 main() 中,我确保两个结构的大小相等。

我现在的问题是: 将 func_wrp 类型的包装函数指针reinterpret_cast 转换为 func_leg 类型的遗留函数指针是否安全? 还是 C++17 中未定义的行为?

我有以下最小的工作示例:

#include <iostream>
#include <cstdint>

//begin of wrapper decls
struct X_wrp {
    std::uint32_t member;
};

using func_wrp = void (*)(const X_wrp* arg);

void caller_wrp(func_wrp func);
//end of wrapper decls

//Legacy C-Code
typedef struct {
    std::uint32_t member;
} X_leg;

typedef void (*func_leg)(const X_leg* arg);

void caller_leg(func_leg func) {
    static X_leg inst{10};
    func(&inst);
}
//End of Legacy C-Code

void callback(const X_wrp* arg) {
    std::cout << arg->member << std::endl;
}

int main() {
    static_assert(sizeof(X_leg)==sizeof(X_wrp));//ensures that there is no oops
    caller_wrp(callback);
    return EXIT_SUCCESS;
}

//begin of wrapper implementations
void caller_wrp(func_wrp func) {
    caller_leg(reinterpret_cast<func_leg>(func)); //is this cast safe?

}
//end of wrapper implementations

最佳答案

不,这不安全,并且在 [expr.call]/6 中被明确称为未定义行为

Calling a function through an expression whose function type is different from the function type of the called function's definition results in undefined behavior.

有关函数指针转换的 reinterpret_cast 文档也强化了这一点 [expr.reinterpret.cast]/6

A function pointer can be explicitly converted to a function pointer of a different type. [ Note: The effect of calling a function through a pointer to a function type ([dcl.fct]) that is not the same as the type used in the definition of the function is undefined ([expr.call]). — end note ] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. [ Note: See also [conv.ptr] for more details of pointer conversions. — end note ]

关于C++-17 : cast function pointer to function with different argument pointer type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60641692/

相关文章:

c++ - 使用imencode()时访问冲突读取位置

c++ - 前向声明类型上的 std::vector

c - 在 C 中使用 typedef 函数指针

c++ - 函数和函数指针等价

C++11 move 语义

c++ - substr 导致段错误

c++ - 使用 variant + reference_wrapper + unique_ptr 表达(非)拥有资源的想法

c++ - 将地址分配给指向指针的指针会产生段错误

c++ - QList 模板化结构

c++ - 指向成员变量的指针作为静态成员