代码之家  ›  专栏  ›  技术社区  ›  Gurwinder Singh

在结构定义中使用guard宏的含义是什么

c++
  •  1
  • Gurwinder Singh  · 技术社区  · 6 年前

    我看到头文件代码如下:

    #ifndef GS
    #define GS
    
    struct GS gs {
    public:
        int n;
        gs(int n) : n{ n } {}
    };
    
    #endif // !GS
    

    使用的目的是什么 GS 在里面 struct GS gs ?如果我删除代码,它的工作原理完全相同。

    我对C++很陌生。我试图在谷歌上搜索,但没有成功。

    4 回复  |  直到 6 年前
        1
  •  3
  •   crashmstr    6 年前

    您是对的,代码的行为没有变化。 没有 显然的 从你展示的代码中获益。

    这是因为

    #define GS
    

    定义 GS 作为 没有什么 因此,在预处理器完成后,不将其包含在结构的声明中没有区别。

    struct gs {
    

    什么 能够 原因是如果有其他工具在预处理器之前读取代码并标记某种用法。

    注意:在注释中,您引用了其他代码。那个代码 可以 ,根据其他标志,将宏设置为 某物 ,如 BOOST_SYMBOL_EXPORT .这可能有特定的意义。根据编译器当时所做的工作,这些类型的用法通常用于将类标记为导出或导入。

        2
  •  1
  •   t.niese    6 年前

    根据您的评论,请参阅:

    struct TORRENT_EXPORT storage_interface {
    }
    

    在哪里? TORRENT_EXPORT 可以定义为 #define TORRENT_EXPORT

    这些宏用于启用与系统/编译/环境相关的选项。

    万一 托伦特出口 如果符号应用作动态链接库,则启用该符号的导出:

    #if defined(_MSC_VER)
        //  Microsoft 
        #define TORRENT_EXPORT __declspec(dllexport)
        #define TORRENT_IMPORT __declspec(dllimport)
    #elif defined(__GNUC__)
        //  GCC
        #define TORRENT_EXPORT __attribute__((visibility("default")))
        #define TORRENT_IMPORT
    #else
        #define TORRENT_EXPORT
        #define TORRENT_IMPORT
        #pragma warning Unknown dynamic link import/export semantics.
    #endif
    

    也可以用于其他预处理或后处理脚本,作为标记,以更容易找到定义。(例如,创建API文档,创建将API粘附到脚本语言的方法,…)

    在其他情况下,它仅在编译器支持时才用于启用语言功能(如 constexpr )

        3
  •  0
  •   iammilind    6 年前

    这种代码唯一可见的好处是确保 宏用于防护,而不是其他用途,即使是意外 .
    见以下场景:

    // file1.h
    #define GS 1234
    
    // file2.h    
    #ifndef GS
    #define GS  // defined for the guarding purpose
    
    #include"file1.h"  // "GS" re-defined for different purpose  
    
    // the redefinition will result in compiler error, due to adding guard in `struct` definition
    struct GS gs { ... };
    
    #endif
    

    现代编译器会对宏的重新定义发出警告。

    尽管如此,这样的保护不会造成任何伤害,并提供了一点好处,以避免任何意外的重新定义。
    通常,现代的IDE-S将以一种独特的方式创建保护,其中包括带有额外下划线的文件扩展名。 _ 例如:

    #ifndef GS_H_
    #define GS_H_
    

    因此,可能不需要这种额外的检查,因为任何开发人员都不会像宏那样创建文件。

        4
  •  0
  •   eerorika    6 年前

    宏的一个目的是由预处理程序将其替换为其他内容(无论宏定义为什么)。

    具体来说,在类键和类名之间放置宏(例如在示例中),将允许宏控制类的属性序列。例如,如果将宏定义为空(例如在示例中),则类将具有空的属性序列:

    #define GS
    struct GS gs {
    // same as
    struct gs {
    

    但宏可以定义为非空:

    #define GS alignas(8)
    struct GS gs {
    // same as
    struct alignas(8) gs {
    

    宏可以在编译时作为参数传递给工具链,从而打开或关闭功能。宏还可以用于检测目标系统,从而启用特定于系统的代码,从而允许依赖系统的程序在多个系统上工作。


    宏的另一个目的是防止头被包含两次。这种宏称为头保护。对头部保护和内容替换(例如在您的示例中)使用相同的宏是令人困惑的和非常规的。