C语言 C 中是否允许空宏定义?他们的行为如何?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13892191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:45:01  来源:igfitidea点击:

Are empty macro definitions allowed in C? How do they behave?

cc-preprocessor

提问by Zeta

Suppose the "empty" macro definition

假设“空”宏定义

#define FOO

Is it valid Standard C? If so, what is FOOafter this definition?

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

回答by Zeta

It is simply a macro that expands to, well, nothing. However, now that the macro has been defined you can check with #if defined(or #ifdef) whether it has been defined.

它只是一个可以扩展为什么都没有的宏。但是,既然已经定义了宏,您可以使用#if defined(或#ifdef)检查它是否已定义。

#define FOO

int main(){
    FOO FOO FOO
    printf("Hello world");
}

will expand to

将扩展到

int main(){

    printf("Hello world");
}

There are certain situations where this comes in very handy, for example additional debug information, which you don't want to show in your release version:

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

/* 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");
    /* ... */
}

Since the macro CONFIG_USE_DEBUG_MESSAGEShas been defined, DEBUG_MSG(x)will expand to print(x)and you will get Entering main. If you remove the #define, DEBUG_MSG(x)expands to an empty do-whileloop and you won't see the message.

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

回答by md5

Yes, empty define is allowed by the standard.

是的,标准允许空定义。

C11 (n1570), § 6.10 Preprocessing directives

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)

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)

A common utilisation is inclusion guards.

一个常见的用途是包含守卫。

#ifndef F_H
# define F_H

#endif

回答by smwikipedia

Empty macro definitions can also be used for self-documentation. The INin the code snippet below is a sample. The code and the comment are both quoted from the EDK II project.

空宏定义也可用于自文档。下面IN的代码片段是一个示例。代码和注释均引用自EDK II 项目

//
// Modifiers for Data Types used to self document code.
// This concept is borrowed for UEFI specification.
//

///
/// Datum is passed to the function.
///
#define IN


typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_RESET)(
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN BOOLEAN                        ExtendedVerification
  );