Ich habe so etwas wie einen Header-Dateicode gesehen:

#ifndef GS
#define GS

struct GS gs {
public:
    int n;
    gs(int n) : n{ n } {}
};

#endif // !GS

Was ist der Zweck der Verwendung von GS in struct GS gs? Der Code funktioniert genauso, wenn ich ihn entferne.

Ich bin ziemlich neu in C ++. Ich habe versucht, dies auf Google ohne Erfolg zu suchen.

c++
1
Gurwinder Singh 20 Jän. 2019 im 17:23

4 Antworten

Beste Antwort

Sie haben Recht, dass sich das Verhalten des Codes nicht ändert. Der von Ihnen angezeigte Code bietet keinen offensichtlichen Nutzen.

Das ist weil

#define GS

Definiert GS als nichts , sodass es nach Abschluss des Präprozessors keinen Unterschied gibt, ihn nicht in die Deklaration der Struktur aufzunehmen.

struct gs {

Was könnte der Grund sein, wäre, wenn es ein anderes Tool gibt, das den Code vor dem Präprozessor liest und eine Verwendung markiert.

Hinweis: In den Kommentaren verweisen Sie auf anderen Code. Dieser Code kann abhängig von anderen Flags das Makro auf etwas setzen, z. B. BOOST_SYMBOL_EXPORT. Das kann dann eine bestimmte Bedeutung haben. Diese Verwendungsarten werden häufig zum Markieren von Klassen als Export oder Import verwendet, je nachdem, was der Compiler gerade tut.

3
crashmstr 20 Jän. 2019 im 14:39

Basierend auf Ihrem Kommentar beziehen Sie sich auf Folgendes:

struct TORRENT_EXPORT storage_interface {
}

Wobei TORRENT_EXPORT als #define TORRENT_EXPORT definiert werden könnte

Diese Art von Makros wird verwendet, um system- / kompilierungs- / umgebungsabhängige Optionen zu aktivieren.

Im Fall von TORRENT_EXPORT, um den Export der Symbole zu ermöglichen, wenn diese als dynamische linke Bibliothek verwendet werden sollen:

#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

Oder kann für andere Skripte vor oder nach der Verarbeitung als Marker verwendet werden, um die Definitionen einfacher zu finden. (z. B. um API-Dokumentationen zu erstellen, um Leim-APIs für Skriptsprachen zu erstellen, ...)

In anderen Fällen werden Sprachfunktionen nur aktiviert, wenn der Compiler dies unterstützt (z. B. constexpr).

1
t.niese 20 Jän. 2019 im 14:45

Der einzige sichtbare Vorteil eines solchen Codes besteht darin, sicherzustellen, dass das Makro zum Zweck von Wachen verwendet wird und auch aus Versehen nichts anderes .
Siehe folgendes Szenario:

// 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

Moderne Compiler geben eine Warnung für die Neudefinition eines Makros aus.

Trotzdem schadet ein solcher Schutz ohnehin nicht und bietet einen kleinen Vorteil, um eine versehentliche Neudefinition zu vermeiden.
Normalerweise erstellen moderne IDEs den Schutz auf einzigartige Weise, einschließlich der Dateierweiterung mit zusätzlichen Unterstrichen _ wie:

#ifndef GS_H_
#define GS_H_

Daher ist eine solche zusätzliche Überprüfung möglicherweise nicht erforderlich, da Entwickler nicht dazu neigen würden, dateiähnliche Makros zu erstellen.

0
iammilind 20 Jän. 2019 im 14:40

Ein Zweck eines Makros besteht darin, dass es vom Vorprozessor durch etwas anderes ersetzt wird (was auch immer dieses Makro sein mag).

Wenn Sie ein Makro zwischen dem Klassenschlüssel und dem Klassennamen platzieren (wie in Ihrem Beispiel), kann das Makro die Attributsequenz der Klasse steuern. Wenn Sie beispielsweise das Makro als leer definieren (wie in Ihrem Beispiel), hat die Klasse eine leere Attributsequenz:

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

Ein Makro kann jedoch so definiert werden, dass es nicht leer ist:

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

Makros können beim Kompilieren als Argument an die Toolkette übergeben werden, wodurch ein Feature ein- oder ausgeschaltet wird. Makros können auch verwendet werden, um das Zielsystem zu erkennen und dadurch systemspezifischen Code zu aktivieren, wodurch ein systemabhängiges Programm auf mehreren Systemen arbeiten kann.


Ein weiterer Zweck eines Makros besteht darin, zu verhindern, dass ein Header zweimal eingeschlossen wird. Ein solches Makro wird als Header Guard bezeichnet. Die Verwendung desselben Makros sowohl für einen Header Guard als auch für das Ersetzen von Inhalten (wie in Ihrem Beispiel) ist verwirrend und unkonventionell.

0
eerorika 20 Jän. 2019 im 14:56