如何从 C 宏的值生成 char 字符串?

发布于 2024-07-07 07:32:00 字数 473 浏览 8 评论 0原文

例如,如何避免将“func_name”写入两次?

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

我想遵循单点事实规则。

C 预处理器版本:

cpp --version

输出:

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

For example, how can I avoid writing the 'func_name' twice?

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

I'd like to follow the Single Point of Truth rule.

Version of C preprocessor:

cpp --version

Output:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

娇柔作态 2024-07-14 07:32:00

害羞的人*给了你答案,但只是胚芽。 在 C 预处理器中将值转换为字符串的基本技术确实是通过“#”运算符,但是对所提出的解决方案进行简单音译会出现编译错误:

#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC

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

语法错误位于“puts()”行- 问题是源中的“杂散#”。

在 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”作为名字。

He who is Shy* gave you the germ of an answer, but only the germ. The basic technique for converting a value into a string in the C pre-processor is indeed via the '#' operator, but a simple transliteration of the proposed solution gets a compilation error:

#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC

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

The syntax error is on the 'puts()' line - the problem is a 'stray #' in the source.

In section 6.10.3.2 of the C standard, 'The # operator', it says:

Each # preprocessing token in the
replacement list for a function-like
macro shall be followed by a parameter
as the next preprocessing token in the
replacement list.

The trouble is that you can convert macro arguments to strings -- but you can't convert random items that are not macro arguments.

So, to achieve the effect you are after, you most certainly have to do some extra work.

#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);
}

I'm not completely clear on how you plan to use the macros, and how you plan to avoid repetition altogether. This slightly more elaborate example might be more informative. The use of a macro equivalent to STR_VALUE is an idiom that is necessary to get the desired result.

#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);
}

* At the time when this answer was first written, shoosh's name used 'Shy' as part of the name.

这样的小城市 2024-07-14 07:32:00

Jonathan Leffler 的解决方案 作品。

一个完整的工作示例:

/** Compile-time dispatch

   gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
*/
#include <stdio.h>

#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)

#ifndef TEST_FUN
#  define TEST_FUN some_func
#endif

#define TEST_FUN_NAME STR(TEST_FUN)

void some_func(void)
{
  printf("some_func() called\n");
}

void another_func(void)
{
  printf("do something else\n");
}

int main(void)
{
  TEST_FUN();
  printf("TEST_FUN_NAME=%s\n", TEST_FUN_NAME);
  return 0;
}

示例:

gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub

输出:

do something else
TEST_FUN_NAME=another_func

Jonathan Leffler's solution works.

A complete working example:

/** Compile-time dispatch

   gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
*/
#include <stdio.h>

#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)

#ifndef TEST_FUN
#  define TEST_FUN some_func
#endif

#define TEST_FUN_NAME STR(TEST_FUN)

void some_func(void)
{
  printf("some_func() called\n");
}

void another_func(void)
{
  printf("do something else\n");
}

int main(void)
{
  TEST_FUN();
  printf("TEST_FUN_NAME=%s\n", TEST_FUN_NAME);
  return 0;
}

Example:

gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub

Output:

do something else
TEST_FUN_NAME=another_func
我还不会笑 2024-07-14 07:32:00
#include <stdio.h>

#define QUOTEME(x) #x

#ifndef TEST_FUN
#  define TEST_FUN func_name
#  define TEST_FUN_NAME QUOTEME(TEST_FUN)
#endif

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

参考:维基百科的 C 预处理器页面

#include <stdio.h>

#define QUOTEME(x) #x

#ifndef TEST_FUN
#  define TEST_FUN func_name
#  define TEST_FUN_NAME QUOTEME(TEST_FUN)
#endif

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

Reference: Wikipedia's C preprocessor page

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文