以下函数指针赋值如何:
exit = (void (*)()) &jump;
与...不同:
exit = &jump;
其中exit是一个定义为的函数指针:
void (*exit) ();
和'jump'是一个声明为:
的函数void jump();
答案 0 :(得分:9)
exit = (void (*)()) &jump;
第一个使用强制转换。这很危险,因为它可能搞砸你的程序,而不会让你知道类型是否匹配,因为它不会在编译时被捕获。 / p>
所以,如果你这样做:
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及更高版本中存在的typeid().name
中的<typeinfo>
:
std::cout << typeid(exit).name << std::endl;
虽然这通常会为函数提供一些奇怪的输出,但您可能会发现一些可以帮助您的信息,如果这两种类型不同,最好的信息就是。
这是一个工作示例,在运行时使用函数指针转换显示问题: http://coliru.stacked-crooked.com/a/47f74e8b6f389812
答案 1 :(得分:3)
它们非常相似。
在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(*)()>
会更安全。
答案 2 :(得分:0)
这两项任务具有相同的效果。第一种方式&#34;演员&#34; &jump
指向不带参数的函数的指针并返回void
,但&jump
已经是那个!