例如,如何避免写两次"func_name"?

#ifndef TEST_FUN
#  define TEST_FUN func_name
#  define TEST_FUN_NAME "func_name"
#endif

我想遵守Single Point of Truth条规则.

C预处理器版本:

$ cpp --version
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)

推荐答案

He who is Shy给了你answer的细菌,但只有细菌.在C预处理器中,将值转换为字符串的基本技术确实是通过"#"运算符实现的,但建议的解决方案的简单音译会导致编译错误:

#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC

#include <stdio.h>
int main(void)
{
    puts(TEST_FUNC_NAME);
    return(0);
}

语法错误在"put()"行-问题是源代码中的"流浪#".

C标准第6.10.3.2节"运营商"中说:

中的每个#预处理令牌

问题在于,您可以将宏参数转换为字符串,但无法转换非宏参数的随机项.

所以,为了达到你想要的效果,你必须做一些额外的工作.

#define FUNCTION_NAME(name) #name
#define TEST_FUNC_NAME  FUNCTION_NAME(test_func)

#include <stdio.h>

int main(void)
{
    puts(TEST_FUNC_NAME);
    return(0);
}

我不完全清楚您计划如何使用宏,以及您计划如何完全避免重复.这个稍微详细一点的例子可能更有信息量.使用等同于STR_VALUE的宏是获得所需结果所必需的习惯用法.

#define STR_VALUE(arg)      #arg
#define FUNCTION_NAME(name) STR_VALUE(name)

#define TEST_FUNC      test_func
#define TEST_FUNC_NAME FUNCTION_NAME(TEST_FUNC)

#include <stdio.h>

static void TEST_FUNC(void)
{
    printf("In function %s\n", TEST_FUNC_NAME);
}

int main(void)
{
    puts(TEST_FUNC_NAME);
    TEST_FUNC();
    return(0);
}

*在第一次写下这个答案时,shoosh的名字使用了"Shy"作为名字的一部分

C++相关问答推荐

定义_MISIX_C_SAL时,在MacOS上编译失败,并出现奇怪错误

AVX-512 BF 16:直接加载bf 16值,而不是从fp 32转换

根据工具链文件中的定义替换单个函数定义

为什么信号量为空= 0,而不是阻塞?

C指针算法在函数参数中的应用

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

`#if`条件中是否允许`sizeof`?

在C++中访问双指针

这个计算C中阶乘的函数正确吗?

如何按顺序将所有CSV文件数据读入 struct 数组?

Tic-tac-toe:从文件加载存储

如果格式字符串的内存与printf的一个参数共享,会发生什么情况?

S,在 struct 中创建匿名静态缓冲区的最佳方式是什么?

用于计算位数和的递归C函数

GETS()在C++中重复它前面的行

当我将偏移量更改为任何非零值时,C中的mmap共享内存出现无效参数错误

C中的空指针是什么(_N)?

可以对两种 struct 类型中的任何一种进行操作的C函数

使用 _Atomic float 时,MSVC 编译的代码会命中调试断言

如何用用户输入的多个字符串填充数组?