C中是否允许空宏定义?他们的表现如何?

41 c c-preprocessor

假设"空"宏定义

#define FOO
Run Code Online (Sandbox Code Playgroud)

它是有效的标准C吗?如果是这样,FOO这个定义之后是什么?

Zet*_*eta 50

它只是一个扩展到,没有任何东西的宏.但是,现在已经定义了宏,您可以检查#if defined(或#ifdef)是否已定义宏.

#define FOO

int main(){
    FOO FOO FOO
    printf("Hello world");
}
Run Code Online (Sandbox Code Playgroud)

将扩大到

int main(){

    printf("Hello world");
}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,这非常方便,例如您不希望在发布版本中显示的其他调试信息:

/* Defined only during debug compilations: */
#define CONFIG_USE_DEBUG_MESSAGES

#ifdef CONFIG_USE_DEBUG_MESSAGES
#define DEBUG_MSG(x) print(x)
#else
#define DEBUG_MSG(x) do {} while(0)
#endif

int main(){
    DEBUG_MSG("Entering main");
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

由于宏CONFIG_USE_DEBUG_MESSAGES已定义,DEBUG_MSG(x)将扩展到print(x)您将获得Entering main.如果您删除#define,DEBUG_MSG(x)扩展到一个空的do- while环,你将不会看到该消息.

  • 这是非常危险的,因为它可能会破坏编译esp.当你有像```if(x)DEBUG_MSG("test")这样的陈述时; 否则DEBUG_MSG("测试");```.我更喜欢用一个无效的语句声明我的空宏,比如``#define DEBUG_MSG(x)do {} while(0)``` (2认同)
  • @Ely 为什么会中断?如果`DEBUG_MSG` 被定义为`#defined DEBUG_MSG(x)`,那么`else DEBUG_MSG("test")` 就变成了`else ;`,这是有效的,因为`;` 是'空语句'。 (2认同)

md5*_*md5 20

是的,标准允许空定义.

C11(n1570),第6.10节预处理指令

control-line:
   # define identifier replacement-list new-line
   # define identifier lparen identifier-list(opt) ) replacement-list new-line
   # define identifier lparen ... ) replacement-list new-line
   # define identifier lparen identifier-list , ... ) replacement-list new-line
replacement-list:
    pp-tokens(opt)
Run Code Online (Sandbox Code Playgroud)

常见的用途是包含警卫.

#ifndef F_H
# define F_H

#endif
Run Code Online (Sandbox Code Playgroud)

  • @ user14284宏没有值.它们扩展到令牌列表.此列表可以为空. (5认同)