为什么函数指针都具有相同的值?

时间:2013-06-30 03:00:20

标签: c++ function-pointers

例如:

using namespace std;
#include <iostream>

void funcOne() {
}

void funcTwo( int x ) {
}

int main() {

  void (*ptrOne)() = funcOne;
  cout << ptrOne << endl;      //prints 1

  void (*ptrTwo)( int x ) = funcTwo;
  cout << ptrTwo << endl;      //prints 1

  int (*ptrMain)() = main;
  cout << ptrMain << endl;     //prints 1

}

有谁知道这背后的原因?起初我以为这是因为函数不存在于内存中,因为我从不调用它们,因此它们永远不会被添加到堆栈中。但即使是指向main函数的指针的值也会输出1。

4 个答案:

答案 0 :(得分:7)

函数指针不会隐式转换为void *,这是operator <<重载的原因。

这由C ++11§4.10/ 2中的省略指定:

  

类型为“指向cv T的指针”的prvalue,其中T是对象类型,可以转换为类型为“指向cv void的指针”的prvalue。将“指向cv T的指针”转换为“指向cv void的指针”的结果指向T类型的对象所在的存储位置的开始,就好像该对象是类型T的最派生对象(1.8) (即,不是基类子对象)。空指针值将转换为目标类型的空指针值。

函数类型不是对象类型。

此外,您甚至无法使用static_cast进行此操作。函数和对象可以存在于完全不同的地址空间(这称为哈佛架构),具有不同大小的指针。将函数指针转换为void *可以 完成reinterpret_cast:它是“有条件支持的”(C ++11§5.2.10/ 8)。这样的void *只能用于打印或转换回原始函数指针类型。

答案 1 :(得分:2)

像这样使用它,或者它将被转换为bool类型。

cout << reinterpret_cast<void*>(ptrOne) << endl;

答案 2 :(得分:1)

C ++中的运算符重载增加了各种令人讨厌的复杂性。 (它可以让你做出很棒的东西 - 但有时它只是令人头痛。)

正如其他答案中所解释的,C ++正在对函数指针进行一些自动类型强制。如果你只是使用好的'C风格printf,你应该得到你期望的结果:

#include <cstdio>

// ...

printf("func1: %p\nfunc2: %p\n", funcOne, funcTwo);

答案 3 :(得分:0)

请改为尝试:

void (*ptrOne)() = funcOne;
cout << reinterpret_cast<void*>(ptrOne) << endl;

void (*ptrTwo)( int x ) = funcTwo;
cout << reinterpret_cast<void*>(ptrTwo) << endl;

int (*ptrMain)() = main;
cout << reinterpret_cast<void*>(ptrMain) << endl;

我认为通常,函数重载规则意味着被调用的<<版本为operator<<(bool),这意味着:

cout << ptrOne << endl;

变换为:

cout << (ptrOne != NULL) << endl;

与以下内容相同:

cout << true << endl;