C++ 如何使用cout打印函数指针?
我想用cout打印出一个函数指针,但发现它不起作用。 但是在我将函数指针转换为(void*)之后,它就工作了,带有%p的printf也是如此,例如C++ 如何使用cout打印函数指针?,c++,C++,我想用cout打印出一个函数指针,但发现它不起作用。 但是在我将函数指针转换为(void*)之后,它就工作了,带有%p的printf也是如此,例如 #include <iostream> using namespace std; int foo() {return 0;} int main() { int (*pf)(); pf = foo; cout << "cout << pf is " << pf <<
#include <iostream>
using namespace std;
int foo() {return 0;}
int main()
{
int (*pf)();
pf = foo;
cout << "cout << pf is " << pf << endl;
cout << "cout << (void *)pf is " << (void *)pf << endl;
printf("printf(\"%%p\", pf) is %p\n", pf);
return 0;
}
#包括
使用名称空间std;
int foo(){return 0;}
int main()
{
int(*pf)();
pf=foo;
cout您可以将函数指针视为该函数机器代码中第一条指令的地址。任何指针都可以视为bool
:0为false,其他所有内容均为true。正如您所观察到的,当转换为void*
并作为流插入运算符的参数提供时(您可以将函数指针视为该函数机器代码中第一条指令的地址。任何指针都可以被视为bool
:0为false,其他所有内容均为true。正如您所观察到的,当转换为void*
并作为流插入运算符的参数提供时(<代码> > p>实际上存在一个超负荷的实际上,有一个超负荷的指针指向<代码>(空洞*)<代码>,如果你想看到它们的值,在C++中做正确的事情(TM)是正确的事(t/p)。
< p>铸造指针指向<代码>(空洞*)< /C> >将它们打印到<代码> cOUT/COD>是正确的(TM)要在C++中做,如果你想看到它们的值。< /P> < P>关于你的编辑,你可以通过通过<代码>未签名char < /Cube指针访问它来打印任何内容。
#include <iostream>
#include <iomanip>
struct foo { virtual void bar(){} };
struct foo2 { };
struct foo3 : foo2, foo { virtual void bar(){} };
int main()
{
void (foo3::*p)() = &foo::bar;
unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);
for (; first != last; ++first)
{
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< (int)*first << ' ';
}
std::cout << std::endl;
}
#包括
#包括
结构foo{virtualvoidbar(){}};
结构foo2{};
结构foo3:foo2,foo{virtualvoidbar(){}};
int main()
{
void(foo3::*p)(=&foo::bar;
unsigned char const*first=重新解释强制转换(&p);
unsigned char const*last=reinterpret_cast(&p+1);
for(;first!=last;++first)
{
std::cout关于编辑,您可以通过unsigned char
指针访问任何内容来打印内容。指向成员函数的指针示例如下:
#include <iostream>
#include <iomanip>
struct foo { virtual void bar(){} };
struct foo2 { };
struct foo3 : foo2, foo { virtual void bar(){} };
int main()
{
void (foo3::*p)() = &foo::bar;
unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);
for (; first != last; ++first)
{
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< (int)*first << ' ';
}
std::cout << std::endl;
}
#包括
#包括
结构foo{virtualvoidbar(){}};
结构foo2{};
结构foo3:foo2,foo{virtualvoidbar(){}};
int main()
{
void(foo3::*p)(=&foo::bar;
unsigned char const*first=重新解释强制转换(&p);
unsigned char const*last=reinterpret_cast(&p+1);
for(;first!=last;++first)
{
关于你的具体问题
我们怎样才能观察一份报告的内容
成员函数指针
答案是,除了将它们转换为bool以表示它指向某个对象或不指向某个对象之外,您不能“观察者”成员函数指针。至少不能以兼容的方式。原因是该标准明确禁止:
4.12脚注57:
57)货币兑换规则
指向成员的指针(从指针到
指向的成员的指针的基成员
派生)与
指向对象的指针的规则(从
指向派生的指针(指向基的指针)
(4.10,第10条)。此倒置为
确保类型安全所必需的。注意
指向成员的指针不是
指向对象的指针或指向对象的指针
函数和转换规则
这些指针的任何一个都不适用于
指向成员的指针。尤其是
无法转换指向成员的指针
空荡荡的*
例如,下面是示例代码:
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
class Gizmo
{
public:
void DoTheThing()
{
return;
};
private:
int foo_;
};
int main()
{
void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
Gizmo g;
(g.*fn)(); // once you have the function pointer, you can call the function this way
bool b = fn;
// void* v = (void*)fn; // standard explicitly disallows this conversion
cout << hex << fn;
return 0;
}
关于你的具体问题,
我们怎样才能观察一份报告的内容
成员函数指针
答案是,除了将它们转换为bool以表示它指向某个对象或不指向某个对象之外,您不能“观察者”成员函数指针。至少不能以兼容的方式。原因是该标准明确禁止:
4.12脚注57:
57)货币兑换规则
指向成员的指针(从指针到
指向的成员的指针的基成员
派生)与
指向对象的指针的规则(从
指向派生的指针(指向基的指针)
(4.10,第10条)。此倒置为
确保类型安全所必需的。注意
指向成员的指针不是
指向对象的指针或指向对象的指针
函数和转换规则
这些指针的任何一个都不适用于
指向成员的指针。尤其是
无法转换指向成员的指针
空荡荡的*
例如,下面是示例代码:
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
class Gizmo
{
public:
void DoTheThing()
{
return;
};
private:
int foo_;
};
int main()
{
void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
Gizmo g;
(g.*fn)(); // once you have the function pointer, you can call the function this way
bool b = fn;
// void* v = (void*)fn; // standard explicitly disallows this conversion
cout << hex << fn;
return 0;
}
在C++11中,可以通过定义运算符的可变模板重载来修改此行为。在C++11中,可以通过定义运算符的可变模板重载来修改此行为(有一次我与函数的地址相交)
(决定之一)
#包括
#包括
void-alexf();
int main()
{
整数输出;
printf(“printf(\“%%p\”,pf)是%p\n”,alexf);
asm(“movl%[输入],%%eax\n”
“movl%%eax,%[输出]\n”
:[输出]“+m”(整数输出)
:[input]“r”(&alexf)
:“eax”、“ebx”
);
std::cout可能(在一段时间内,我一直在讨论函数的地址)
(决定之一)
#包括
#包括
void-alexf();
int main()
{
整数输出;
printf(“printf(\“%%p\”,pf)是%p\n”,alexf);
asm(“movl%[输入],%%eax\n”
“movl%%eax,%[输出]\n”
:[输出]“+m”(整数输出)
:[input]“r”(&alexf)
:“eax”、“ebx”
);
std::cout+1。唯一适用于函数指针的标准转换是(左值到右值的转换除外)到bool
的转换。值得注意的是,您必须执行重新解释
才能转换int(*)()<代码> >代码> Vult*/Cux> .avaar有一个文档覆盖函数指针的转换规则吗?最终文件将是C++标准,第4节[CONV]和5.2 [Exp.PoST ]。标准不是免费的,但您可以得到最新草案H。
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
class Gizmo
{
public:
void DoTheThing()
{
return;
};
**void DoTheOtherThing()
{
return;
};**
private:
int foo_;
};
int main()
{
void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
Gizmo g;
(g.*fn)(); // once you have the function pointer, you can call the function this way
bool b = fn;
// void* v = (void*)fn; // standard explicitly disallows this conversion
cout << hex << fn;
**void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing;
bool same = fnOther == fn;
bool sameIsSame = fn == fn;**
return 0;
}
#include<iostream>
namespace function_display{
template<class Ret, class... Args>
std::ostream& operator <<(std::ostream& os, Ret(*p)(Args...) ){ // star * is optional
return os << "funptr " << (void*)p;
}
}
// example code:
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main(){
using namespace function_display;
// ampersands & are optional
std::cout << "1. " << &fun_void_void << std::endl; // prints "1. funptr 0x40cb58"
std::cout << "2. " << &fun_void_double << std::endl; // prints "2. funptr 0x40cb5e"
std::cout << "3. " << &fun_double_double << std::endl; // prints "3. funptr 0x40cb69"
}