首页UC › __func__标识符

__func__标识符

__func__是C99标准里面预定义标识符, 它是一个static const char[],
会在每一个使用__func__的函数里隐式定义.

下面是ISO9899里的例子
#include <stdio.h>
void myfunc(void)
{
printf(“%s/n”, __func__);
/* … */
}

输出: myfunc

据我所知好像只有GCC才支持这个标识符, 其它编绎器厂商要么就没支持要么是扩展为其它. 如VC7里就只有__FUNCTION__和GCC里__PRETTY_FUNCTION__.
1,然而这个特性我所感兴趣的是在C++里它能输出什么?
2,它是否能用于构造函数的初始化列表?
3,它是否能用于默认参数?
4,除用于异常信息或DEBUG信息外还有什么用途?
5,应该用标准的还是用扩展的标识符?

第一个问题比较好解决,只要写些测试代码就行了.
因为环境的关系我只能用GCC 3.4.2做测试, 在GCC里除__func__还有
__FUNCTION__和__PRETTY_FUNCTION__, 前者两个所输出的和上面那个例的的结果一样只有一个函数名, 而后者则比较长细地列出函数的信息.

下面是测试在C++里__func__这个特性的输出.
#include <cstdio>
#include <cstdlib>

#define EXTERN_2

#define _INFO(n) puts(n)
#ifdef STANDARD
#define INFO() _INFO(__func__)
#endif
#ifdef EXTERN_1
#define INFO() _INFO(__FUNCTION__)
#endif
#ifdef EXTERN_2
#define INFO() _INFO(__PRETTY_FUNCTION__)
#endif
namespace _private{
class TestBase{
public:
virtual ~TestBase(){}
};

class Test: public TestBase{
public:
Test(){INFO();}

template<class T>
Test(T){INFO();}

Test(int, …){INFO();}

~Test(){INFO();}

static void bar(){INFO();}

template<class T>
operator T()const{
INFO();
return T();
}

friend __stdcall void foo(TestBase& t){INFO();};

struct Widget{};
};
}

int main(){
using namespace _private;
using namespace std;
{
Test t1;
Test t2(0, ‘a’, ‘b’);
Test const t3=Test(0.);
Test::bar();
foo(t1);
int i=t3;
Test::Widget wg=t3;
}
system(“pause”);
return 0;
}

在默认为__PRETTY_FUNCTION__的输出是:
_private::Test::Test()
_private::Test::Test(int, …)
_private::Test::Test(T) [with T = double]
static void _private::Test::bar()
void _private::foo(_private::TestBase&)
_private::Test::operator T() const [with T = int]
_private::Test::operator T() const [with T = _private::Test::Widget]
virtual _private::Test::~Test()
virtual _private::Test::~Test()
virtual _private::Test::~Test()
Press any key to continue . . .
在GCC里的基本格式是:
(static or virtual)namespace::class::function(const or volatile), 而且对template还有附加描述, 但可惜没有对调用规范的描述.

第二个问题是”它是否能用于构造函数的初始化列表?”
为什么会这样问呢? 因为据标准说它只是函数体内隐式的定义. 即:
struct A{
A():pstr(str){  // err
static const char str[]=”hello”;
}
const char* pstr;
};
但这样是错的, 在初始化列表里的str会被认为是还没声明的. 但我用__func__
却没有报错.
struct A{
A():pstr(__func__){  // ok
static const char str[]=”hello”;
}
const char* pstr;
};

嗯, 看来它是先于函数体的.(我只用GCC试我还没肯定这个行为是否正确), 因为这个不确定所以我想了第三个问题”它是否能用于默认参数?”.

简单的代码试验说明这是不能的:
void foo(char const* pstr=__func__); // err
再试试
void foo(char const* pstr=__FUNCTION__); // ok
竟然编绎通过了, 但pstr==””. (看来这是__func__和__FUNCTION__的区别了)
看来它不是能作默认参数的了.

嗯, 真的吗?是否会有特例呢? 于是有想了Local Class的情况:

void foo(){
__func__;  // 必须在bar的定义前先显式用一次__func__

struct A{
void bar(char const* pstr=__func__){ // ok
puts(pstr);
}
};

A a;
a.bar();   // 输出的是”foo”而不是”bar”
}

对于第四个问题我没想到太好的例子, 大概只想到两个:
(base64的编码表)
char
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789(int i){
if(i==62)return ‘+’;
if(i==63)return ‘/’;
return __func__[i];
}

char
(*EnBase64Tab)(int)=&ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789;
(COMMAND解释事例)
class Command{
virtual void do_execute()=0;
public:
static void Execute(const char* script[]){
/*
foreach(vec)
if(script[i]==vec.iter)
*iter.do_execute();
*/
}
protected:
static  CMDVEC vec;
};

CMDVEC Command::vec;

class Edit: public Command{
virtual void do_execute(){}
static Edit edit;
Edit(){Command::vec.push_back(std::make_pair(__func__, this));}
};
Edit Edit::edit;

class Search: public Command{
virtual void do_execute(){}
static Search search;
Search(){Command::vec.push_back(std::make_pair(__func__, this));}
};
Search Search::search;

就是说若你的应用中函数和它的名子有很大关联的时候可以用上它.

第五个问题是用那个比较好?
我查了一下网上的资料俱称__FUNCTION__只是__func__的一个宏. 但我实际在GCC的预处理器上试过并不是这样. 嗯我油印得一般情况下应该用__func__, 因为它比较短. 而且它是标准里指定的.

对于这个新特性我个人理解基本上是这样了, 还需要注意的是在不支持新特性的编绎器上不要用__func__作为变量名, 即使你认为不会用任何新行性, 也应该注意这点.

发表评论