输出函数名的方法:宏函数、__func__、__PRETTY_FUNCTION__、__FUNCDNAME__、__FUNCSIG__、__FUNCTION__、source_location

参考文档:

  1. https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
  2. 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/在线编译器进行测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值