我正在编写一些大型宏,并认为如果我可以为它们添加注释会很好,就像这样:
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() \ // this does...
SOME_OTHER_FUNCTION_CALL()
当我跑步时,我得到:
prog.cpp:9:2:错误:在程序中隐藏'\'
有没有办法解决这个问题,或者只是不可能评论多行宏?
答案 0 :(得分:19)
除宏的最后一行外,没有办法在宏中使用// comments
。
正如Paul R所说,/* comment */
确实有效,似乎是唯一的选择:
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() /* this does... */ \
SOME_OTHER_FUNCTION_CALL()
原因如下。 Standard for Programming Language C ++(我只能访问此草案)指定源文件的物理行可以连接成编译器将使用\
后跟换行符看到的逻辑行:
删除反斜杠字符()后面紧跟一个换行符的每个实例,拼接物理源代码行以形成逻辑源代码行。只有任何物理源线上的最后一个反斜杠才有资格成为这种拼接的一部分。
可以在预处理器输出中轻松检查:使用
创建file.cpp
pri\
ntf ("Hell\
o world"\
);
然后
cpp file.cpp
给出
printf ("Hello world");
或
printf
("Hello world");
这是编译器看到的内容(在Ubuntu中检查;您的里程可能会有所不同)。
现在,将此规则应用于多行宏
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() \
SOME_OTHER_FUNCTION_CALL()
被预处理器理解为
#define SOME_BIG_MACRO(input) SOME_FUNCTION_CALL() SOME_OTHER_FUNCTION_CALL()
因为忽略了所有\
和下一个换行符。
类似地,
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() /* this does... */ \
SOME_OTHER_FUNCTION_CALL()
被预处理器视为
#define SOME_BIG_MACRO(input) SOME_FUNCTION_CALL() /* this does... */ SOME_OTHER_FUNCTION_CALL()
然而,
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() \ // this does...
SOME_OTHER_FUNCTION_CALL()
变成两行:
#define SOME_BIG_MACRO(input) SOME_FUNCTION_CALL() \ // this does...
SOME_OTHER_FUNCTION_CALL()
因为第二个\
后面没有换行符,因此会被保留,而换行符不会出现\
。这会导致编译错误。
虽然
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() // this does... \
SOME_OTHER_FUNCTION_CALL()
变成一行:
#define SOME_BIG_MACRO(input) SOME_FUNCTION_CALL() // this does... SOME_OTHER_FUNCTION_CALL()
这在语法上是正确的,但宏不完整。一些编译器将此报告为错误,因为很可能这不是程序员的意图。其他人,例如Ubuntu cc
,默默地应用标准定义的规则。
由于宏只能占用一条逻辑行(虽然有几条物理行,使用换行符转义机制),此行上的任何// comment
都会导致宏的其余部分为忽略。
结论:// comment
只能出现在(多行或单行)宏的末尾,而/* comment */
可以完美地在宏内使用。
答案 1 :(得分:3)
行评论//不会做,只会阻止评论/ * ... * / e.g。
#define SOME_BIG_MACRO(input)\
SOME_FUNCTION_CALL() /* this does... */ \
SOME_OTHER_FUNCTION_CALL()
答案 2 :(得分:2)
根据这个答案:
https://stackoverflow.com/a/11722479/3545094
在预处理期间展开宏之前,注释被一个空格字符替换。
\ escapes一个字符,必须是\ n才能让宏工作,正如之前的答案/评论所解释的那样。
这意味着注释必须位于宏之前的\之前,因此//将无效,因为您将删除宏所需的\。