【问题标题】:Printing function addresses always prints 1 on linux打印函数地址在linux上总是打印1
【发布时间】:2014-08-28 00:01:25
【问题描述】:

我正在开发一个处理不同变量和函数地址的 c++ 程序。

当我在基于 Linux 的操作系统上编译我的程序时,包括 main 在内的所有函数都获得 1 的地址,而不是像其他变量那样的 8 位十六进制数字,这在 Windows 中没有发生。

我写了一小段代码来解释这个问题

#include <iostream>
using namespace std;
void Function1();
void Function1(){ 
}

int main(){
    int tmp;
    void (*a) ()=&Function1;
    cout<<a<<endl;
    cout<<&Function1<<endl;
    cout<<&main<<endl;
    return 0;
}

对于所有 3 个 cout 调用,输出为 1 而不是虚拟地址。

【问题讨论】:

  • “这在 Windows 中没有发生” 应该做到了。
  • @LightnessRacesinOrbit 我刚试过,确实没有,VS2013
  • @0d0a: 嗯,VS2012 一样。这是其中一个错误。 stackoverflow.com/q/25540033/560648
  • 请修正缩进

标签: c++ printing cout virtual-memory


【解决方案1】:

指针被转换为另一种类型,bool,因为它是一个函数指针,并且在函数指针的 &lt;iostream&gt; 库中没有 operator&lt;&lt; 的重载(因为此类类型的数量是无限的) .指针指向某个非零地址,因为它已经用函数的地址进行了初始化——所以它被转换为 1(只有 0x0 地址会给你布尔值 0)。

解决方案

要断言正确的行为,您应该将指针转换为void*,以便您可以使用operator&lt;&lt; overload for void*

ostream & operator <<( ostream &, const void * );

例子:

void Function1(){}

int main() {
    void ( *a) () = &Function1;
    cout << ( void*)( a) << endl;
    /* or better - being explicit about harshness of this design */
    cout << reinterpret_cast< void*> ( a) <, endl;
}

http://ideone.com/Fne4Mu


C++ 标准 n3337 § 4.12 布尔转换 [conv.bool]

1 算术、无范围枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。将零值、空指针值或空成员指针值转换为 false;任何其他值都将转换为 true。 std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果是假的。

【讨论】:

  • 请注意,在标准 C++ 中,将函数指针强制转换为 void* 是非法的(请参阅 stackoverflow.com/questions/36645660),但某些编译器可能允许将其作为扩展,但您不应依赖它。
【解决方案2】:

&lt;&lt; 没有采用函数指针的标准重载;因此,指针被转换为bool(因为这是一个合法的隐式转换),如果您在流上使用了std::boolalpha 操纵器,则给出1true

如果你想要地址,你必须将它显式转换为对象指针:

std::cout << reinterpret_cast<void*>(&Function1) << std::endl;

【讨论】:

  • 请注意,在标准 C++ 中,将函数指针强制转换为 void* 是非法的(请参阅 stackoverflow.com/questions/36645660),但某些编译器可能允许将其作为扩展,但您不应依赖它。
【解决方案3】:

如果我把你的代码改成下面这样,函数指针地址就会正确显示:

void Function1() {
}

int main() {
    void*a = (void*)&Function1;
    cout<<a<<endl;
    cout<< (void*)&Function1<<endl;
    cout<< (void*)&main<<endl;
    return 0;
}

输出:

0x8048710
0x8048710
0x8048570

请查看working sample here


问题是,有一个标准的运算符重载可用于

ostream& operator<<(ostream&,void*)

但不适用于函数指针

ostream& operator<<(ostream&,void (Function1Type*)())

和最不有效的转换绘制

ostream& operator<<(ostream&,bool)

除了0x00000000 之外的所有内容都是true

【讨论】:

  • @AbdulazizAldyaf 如果你想感谢我或社区,你可以考虑accepting this answer:只需点击我帖子下方的那个白色大勾号(你甚至会这样做可以获得代表)。
猜你喜欢
  • 2012-06-11
  • 2017-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多