Bla*_*iev 5 c stringification c-preprocessor
我正在定义一个宏,它计算为一个常量字符串,保存文件名和行号,用于记录目的.
它工作正常,但我无法弄清楚为什么需要2个额外的宏 - STRINGIFY而且TOSTRING,当直觉暗示时__FILE__ ":" #__LINE__.
#include <stdio.h>
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define THIS_ORIGIN (__FILE__ ":" TOSTRING(__LINE__))
int main (void) {
  /* correctly prints "test.c:9" */
  printf("%s", THIS_ORIGIN);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎是一个丑陋的黑客.
具体是什么,这样逐步发生阶段有人能解释__LINE__正确字符串化,为什么既不__FILE__ ":" STRINGIFY(__LINE__)和__FILE__ ":" #__LINE__作品?
因为扩张的顺序.在海湾合作委员会的文件说:
宏参数在被替换为宏体之前完全是宏扩展的,除非它们被字符串化或粘贴到其他标记.替换后,将再次扫描整个宏体(包括替换参数),以便扩展宏.结果是参数被扫描两次以扩展其中的宏调用.
因此,如果参数将被字符串化,则不会首先展开它.您将在括号中获取文字文本.但如果它被传递给另一个宏,它就会被扩展.因此,如果要扩展它,则需要两个级别的宏.
这样做是因为在某些情况下您不希望在字符串化之前扩展参数,最常见的是assert()宏.如果你写:
assert(MIN(width, height) >= 240);
Run Code Online (Sandbox Code Playgroud)
你想要的消息是:
Assertion MIN(width, height) >= 240 failed
Run Code Online (Sandbox Code Playgroud)
而不是MIN宏扩展到的一些疯狂的东西(在gcc中它使用了几个特定于gcc的扩展,并且是非常长的IIRC).