打印表达式并对其求值的宏(使用 __STRING)

发布于 2024-07-09 18:50:02 字数 471 浏览 11 评论 0原文

为了学习和演示,我需要一个宏来打印其参数并对其进行评估。 我怀疑这是一个非常常见的案例,甚至可能是一个常见问题解答,但我找不到实际的参考资料。

我当前的代码是:

#define PRINT(expr) (fprintf(stdout, "%s -> %d\n", __STRING(expr), (expr)))

然后:

PRINT(x & 0x01);

它工作正常,但我不确定 __STRING 宏的合法状态,特别是因为它位于私有 __ 命名空间中。

所以,我的问题是:

  1. 有没有更好的方法来编写这个宏?
  2. __STRING 是标准/伟大/邪恶吗?
  3. 如何利用现有的搜索工具来查找__STRING? SO 的搜索引擎只搜索包含字符串的任何内容:-(

For learning and demonstrating, I need a macro which prints its parameter and evaluates it. I suspect it is a very common case, may be even a FAQ but I cannot find actual references.

My current code is:

#define PRINT(expr) (fprintf(stdout, "%s -> %d\n", __STRING(expr), (expr)))

and then:

PRINT(x & 0x01);

It works fine but I am not sure of the legal status of the __STRING macro, specially since it is in the private __ namespace.

So, my questions:

  1. Is there a better way to write this macro?
  2. Is __STRING standard/great/evil?
  3. How to use existing search tools to find about __STRING? SO's search engine just searches anything containing string :-(

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

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

发布评论

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

评论(4

一桥轻雨一伞开 2024-07-16 18:50:02

类似的东西

#define PRINT(expr) (fprintf(stdout, "%s -> %d\n", #expr, (expr)))

可能就是你想要的。 # 是字符串化运算符。

Something like

#define PRINT(expr) (fprintf(stdout, "%s -> %d\n", #expr, (expr)))

is probably what you want. # is the stringification operator.

dawn曙光 2024-07-16 18:50:02

您可以使用 # 预处理器标记,将其后面的参数转换为字符串文字:

#include <stdlib.h>
#include <stdio.h>

#define STR(x) #x
#define PRINT(expr) (fprintf(stdout, "%s -> %d\n", STR(expr), (expr)))

int main(void)
{
    int x = 7;

    PRINT(x & 0x01);

    return EXIT_SUCCESS;
}
  1. 这绝对不是标准的,这是我第一次遇到它; 这并不奇怪,因为乍一看,它似乎并没有比上面的 STR() 宏做更多的事情。

  2. Google 似乎工作正常。

You can use the # preprocessor token which converts the parameter following it to a string literal:

#include <stdlib.h>
#include <stdio.h>

#define STR(x) #x
#define PRINT(expr) (fprintf(stdout, "%s -> %d\n", STR(expr), (expr)))

int main(void)
{
    int x = 7;

    PRINT(x & 0x01);

    return EXIT_SUCCESS;
}
  1. It's definitely not standard, and this is the first time I've come across it; not surprising as it doesn't seem to do much more than the STR() macro above, at a first glance.

  2. Google seems to work fine.

弱骨蛰伏 2024-07-16 18:50:02

glibc 自(至少)版本 1.04 (1992-09-03) 甚至更早以来一直提供 __STRING

/usr/include/sys/cdefs.h:

#define __CONCAT(x,y)   x ## y
#define __STRING(x) #x

当时它们都在glibc中使用。 目前,__STRING 未在 glibc 中使用,但保留在那里供应用程序使用。

在 Linux 上,您可以依赖这些。 IIUC、__STRING__CONCAT 在 NetBSD 1.3 中被采用; Solaris 两者都不提供。 其他操作系统可能有所不同。

It is glibc who has been providing __STRING since (at least) version 1.04 (1992-09-03), maybe earlier.

/usr/include/sys/cdefs.h:

#define __CONCAT(x,y)   x ## y
#define __STRING(x) #x

They were both used in glibc back then. Currently, __STRING is not used in glibc, but is kept there for app use.

On Linux, you may rely upon these. IIUC, __STRING and __CONCAT were adopted in NetBSD 1.3; Solaris provides neither. Other OSes may vary.

沧笙踏歌 2024-07-16 18:50:02

对于产生可能未定义的值的宏,我能想到的最好的方法(可怕但有效):

#define PRINT_UNDEF(x) printf("The macro " #x " is not defined.\n")
#define PRINT_INT(x) printf("The macro " #x " has a value of %d.\n", x)
// More definitions for macros producing string, float etc. 

然后你可以这样称呼它:

#ifndef MACRO_NAME
    PRINT_UNDEF(MACRO_NAME);
#else
    PRINT_INT(MACRO_NAME);
#endif

为要打印的每个宏复制这五行,并将 MACRO_NAME 替换为宏的名称。 在 PRINT_UNDEF 和 PRINT_INT 内部,您可以使用表达式而不仅仅是宏名称,但 #ifndef 必须仅包含宏名称。

The best I could come up with (horrible but working) for macros producing values that may be undefined:

#define PRINT_UNDEF(x) printf("The macro " #x " is not defined.\n")
#define PRINT_INT(x) printf("The macro " #x " has a value of %d.\n", x)
// More definitions for macros producing string, float etc. 

And then you call it like

#ifndef MACRO_NAME
    PRINT_UNDEF(MACRO_NAME);
#else
    PRINT_INT(MACRO_NAME);
#endif

Copy these five lines for every macro that you want to print, and replace MACRO_NAME with the name of your macro. Inside the PRINT_UNDEF and PRINT_INT, you can use expressions instead of just macro names, but the #ifndef must contain just the macro name.

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