在函数指针赋值中进行强制转换
Casting in function pointer assignment
以下函数指针分配如何:
exit = (void (*)()) &jump;
不同于:
exit = &jump;
其中 exit 是一个函数指针,定义为:
void (*exit) ();
而"jump"是一个声明为的函数:
void jump();
exit = (void (*)()) &jump;
第一个使用强制铸造。这是危险的,因为它可能会搞砸你的程序,而不会让你知道类型是否不匹配,因为它不会在编译时被捕获。
因此,如果您要这样做:
int func() {return 1;}
auto exit = (void (*)()) &func;
。那会很糟糕。但是,最好执行以下操作:
exit = &jump;
第二个使用编译时类型检查。这更安全,因为编译器将在编译时检查类型。这为您提供了更强大的类型保证。
最好的选择是使用 static_cast<void(*)()>
它是类型安全的,并告诉程序员更多你试图做什么的意图。
auto exit = static_cast<void(*)()>(&func);
如果您有C++,可以尝试以下操作:
如果您不想关心类型,请使用 auto
。
auto exit = &func
这将确保类型匹配。如果要检查类型,请使用 C++11 及更高版本中存在的<typeinfo>
中的typeid().name
:
std::cout << typeid(exit).name << std::endl;
虽然这通常会为函数提供一些奇怪的输出,但您可能会找到一些可以帮助您的信息,最好的信息是如果两种类型不同。
下面是一个工作示例,显示了运行时使用函数指针强制转换的问题: http://coliru.stacked-crooked.com/a/47f74e8b6f389812
它们非常相似。
在 C 中,如果函数和类型与描述完全一致:
void (*exit) ();
void jump();
exit = (void (*)()) &jump;
exit = &jump;
是相同的。
现在当我更改jump
时会发生什么:
int jump();
现在我们正在运行未定义的行为,如果我们在以下之后调用exit
,则不会发生错误或警告:
exit = (void (*)()) &jump;
但是在这里我们得到一个类型错误:
exit = &jump;
此外,还可能发生更微妙的差异 - 例如jump
可能获得调用约定,因此无法存储在exit
中,并且事情会中断。
在C++中,还有另一个微妙的区别。 如果 jump
是一个重载函数,并且 exit 不是原始函数指针(而是std::function<void()>
(,则第一个可以编译,而第二个可能不会。 将名称强制转换为函数指针类型可以触发重载解析,否则某些代码将无法工作。
但是,使用static_cast<void(*)()>
会更安全。
这两个赋值具有相同的效果。第一种方法&jump
"强制转换"到指向不带参数并返回void
的函数的指针,但&jump
已经是这样了!
- 转换函数,将 std::数组的双精度作为参数或双精度作为参数单独转换
- C++:用户定义的显式类型转换函数错误
- 为什么下面带有非常量转换函数的代码没有歧义?
- 为什么转换函数声明不需要至少一个定义类型说明符
- PCL:当我在setConditionFunction中使用std::bind 时,没有合适的转换函数
- C++ 通过自定义赋值运算符隐式转换函数参数
- 当我使用 void 函数的返回值(通过强制转换函数指针)时,究竟会发生什么?
- 在C++中自动向下转换函数参数
- static_cast:转换函数模板——它们真的有效吗
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类
- 隐式转换函数的返回对象时是否会影响性能?
- C++不存在合适的转换函数
- 为什么允许 int 和 const int 使用不同的转换函数?
- 使用转换函数直接初始化
- 为什么用户定义的转换函数模板不能有推导的返回类型?
- 为什么我会收到转换函数错误
- 选择用于赋值初始化的转换函数的优先级
- 我收到错误:没有合适的转换函数从 std::basic_istream<char、std::char_traits<char>> 到 char 存在
- 具有转换函数的 lambda,指向具有 C++ 链接的函数的指针
- 使用模板和部分专用化生成类型转换函数