简体   繁体   English

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

[英]Why do function pointers all have the same value?

For example: 例如:

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

}

Does anyone know the reasoning behind this? 有谁知道这背后的原因? At first I thought it was because the functions don't exist in memory since I never call on them, and thus they never get added to the stack. 起初我以为这是因为函数不存在于内存中,因为我从不调用它们,因此它们永远不会被添加到堆栈中。 But even the value of a pointer to the main function prints out 1. 但即使是指向main函数的指针的值也会输出1。

Function pointers do not implicitly convert to void * , which is what operator << overloads on. 函数指针不会隐式转换为void * ,这是operator <<重载的内容。

This is specified by omission in C++11 §4.10/2: 这由C ++11§4.10/ 2中的省略指定:

A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. 类型为“指向cv T的指针”的prvalue, 其中T是对象类型,可以转换为类型为“指向cv void的指针”的prvalue。 The result of converting a “pointer to cv T” to a “pointer to cv void” points to the start of the storage location where the object of type T resides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject). 将“指向cv T的指针”转换为“指向cv void的指针”的结果指向T类型的对象所在的存储位置的开始,就好像该对象是类型T的最派生对象(1.8) (即,不是基类子对象)。 The null pointer value is converted to the null pointer value of the destination type. 空指针值将转换为目标类型的空指针值。

Function types are not object types. 函数类型不是对象类型。

Moreover, you can't even do it using static_cast . 而且,你甚至不能使用static_cast来做。 Functions and objects may live in completely different address spaces (this is called Harvard architecture), with differently-sized pointers. 函数和对象可以存在于完全不同的地址空间(这称为哈佛架构),具有不同大小的指针。 Converting a function pointer to void * can maybe be done with reinterpret_cast : it's "conditionally-supported" (C++11 §5.2.10/8). 转换函数指针void * 也许可以用做reinterpret_cast :它的“有条件支持”(C ++ 11§5.2.10/ 8)。 Such a void * should only be used for printing or conversion back to the original function pointer type. 这样的void *只应用于打印或转换回原始函数指针类型。

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

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

Operator overloading in C++ adds all sorts of nasty complexities. C ++中的运算符重载增加了各种令人讨厌的复杂性。 (It lets you do awesome stuff too—but sometimes it's just a headache.) (它可以让你做出很棒的东西 - 但有时它只是令人头疼。)

As explained in the other answers, C++ is doing some automatic type coercion on your function pointers. 正如其他答案中所解释的,C ++正在对函数指针进行一些自动类型强制。 If you just use the good ol' C-style printf you should get the results you're expecting: 如果你只是使用好的'C风格的printf你应该得到你期望的结果:

#include <cstdio>

// ...

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

Try this instead: 试试这个:

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;

I think normally, function overloading rules mean that the version of << being called is operator<<(bool) , which means: 我认为通常,函数重载规则意味着<<被调用的版本是operator<<(bool) ,这意味着:

cout << ptrOne << endl;

Gets transformed into: 变成:

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

Which is the same as: 这与以下相同:

cout << true << endl;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM