参考文档:
- https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
- https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?redirectedfrom=MSDN&view=msvc-160
一、使用宏函数输出函数名
1.自定义宏函数:TO_STR
将传入的参数转为字符串,可用于输出变量名,如下示例:
// test.c
#include<stdio.h>
/* 将传入得参数转为常量字符串 */
#define TO_STR(var) (#var)
int main()
{
// TO_STR
int ia = 10;
double da = 10.234;
printf("%s = %d\n", TO_STR(ia), ia);
printf("%s = %g\n", TO_STR(da), da);
// Sample Output
// -------------------------------------------------
// ia = 10
// da = 10.234
return 0;
}
2.自定义宏函数:PRINT_VAL、PRINT_FUNC
/* 打印传入变量的 名称字符串,值,地址 /
#define PRINT_VAL(str) printf ("name: %s value: %s address: %p\n",#str, str, &str)
/ 打印传入函数的 函数名,调用结果,地址 */
#define PRINT_FUNC(str) printf ("name: %s() value: %s address: %p\n",#str, str(), &str)
// test.c
#include<stdio.h>
/* 打印传入变量的 名称字符串,值,地址 */
#define PRINT_VAL(str) printf ("name: %s value: %s address: %p\n",#str, str, &str)
/* 打印传入函数的 函数名,调用结果,地址 */
#define PRINT_FUNC(str) printf ("name: %s() value: %s address: %p\n",#str, str(), &str)
const char* func() { return "this is a test."; } // 测试函数
int main()
{
char str1[] = "This is the variable str1";
const char* pfunc = func();
// PRINT_VAL
PRINT_VAL(str1);
PRINT_VAL(pfunc);
// PRINT_FUNC
PRINT_FUNC(func);
// Sample Output
// -------------------------------------------------
// name: str1 value : This is the variable str1 address : 012FFAE8
// name : pfunc value : this is a test.address : 012FFADC
// name : func() value : this is a test.address : 00A110E6
return 0;
}
二、使用预定义宏输出函数名
相关参考文档已在博文顶部提出,这里就不再赘述,下面简单演示一下几种宏的功能。
1.__func__
__func__
是一个隐式声明的标识符,在函数内部使用函数名称时,该标识符可扩展到包含函数名称的字符数组变量。它在 C99 中添加到 C。
// test.c
#include <stdio.h>
void example() {
printf("%s\n", __func__);
} // prints "example"
int main()
{
example();
return 0;
}
2.__PRETTY_FUNCTION__
// test.cpp
extern "C" {
extern int printf(char*, ...);
}
class A {
public:
void sub(int i)
{
printf("__FUNCTION__ = %s\n", __FUNCTION__);
printf("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
// Sample Output
// -------------------------------------------------
// __FUNCTION__ = sub
// __PRETTY_FUNCTION__ = void A::sub(int)
}
};
int
main(void)
{
A ax;
ax.sub(0);
return 0;
}
(注:由于VS 编译器下没有提供__PRETTY_FUNCTION__,这里使用gcc进行编译。)
3.__FUNCDNAME__
、__FUNCSIG__
、__FUNCTION__
函数名 : __FUNCTION__ 、函数修饰 : __FUNCDNAME__ 、函数签名 : __FUNCSIG__
// test.cpp
// 测试一,类对象输出函数信息
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
void show(int i)
{
cout << "函数名 : " << __FUNCTION__ << endl;
cout << "函数修饰: " << __FUNCDNAME__ << endl;
cout << "函数签名: " << __FUNCSIG__ << endl;
// Sample Output
// -------------------------------------------------
// 函数名 : 函数名: A::show
// 函数修饰: 函数修饰 : ? show@A@@QAEXH@Z
// 函数签名: 函数签名 : void __thiscall A::show(int)
}
};
// 测试二:普通函数输出函数信息
void exampleFunction()
{
cout << "函数名 : " << __FUNCTION__ << endl;
cout << "函数修饰: " << __FUNCDNAME__ << endl;
cout << "函数签名: " << __FUNCSIG__ << endl;
// Sample Output
// -------------------------------------------------
// 函数名 : exampleFunction
// 函数修饰: ? exampleFunction@@YAXXZ
// 函数签名 : void __cdecl exampleFunction(void)
}
int main(void)
{
A ax;
ax.show(0); // 测试一
exampleFunction();// 测试二
return 0;
}
4.source_location
参考:https://zh.cppreference.com/w/cpp/utility/source_location
相关函数:
file_name 返回此对象所表示的文件名
function_name 返回此对象表示的函数名,若它存在
示例代码:
#include <iostream>
#include <source_location>
/* 返回此对象表示的函数名 */
#define FUNC_NAME std::source_location::current().function_name()
/* 返回此对象所表示的文件名 */
#define FILE_NAME std::source_location::current().file_name()
class A
{
private:
public:
// 构造函数
A() { std::cout << FUNC_NAME << std::endl; }
// 拷贝构造
A(const A& rhs) { std::cout << FUNC_NAME << std::endl; }
// 普通成员函数
void printFileName() {
std::cout << FUNC_NAME << std::endl;
std::cout << FILE_NAME << std::endl; // 输出文件名
}
};
int main()
{
A a; // 调用构造
A b(a); // 调用拷贝构造
a.printFileName(); // 调用普通成员函数
// Sample Output
// -------------------------------------------------
// A::A()
// A::A(const A&)
// void A::printFileName()
// prog.cc
return 0;
}
注:头文件<source_location>需要C++20支持。如您的编译器不支持C++20,可以使用https://wandbox.org/在线编译器进行测试。