Verwendung von #pragma unter Linux

Verwendung der vorkompilierten Direktive #pragma

Original: https://blog.csdn.net/tigerjibo/article/details/7000861 

Als ich mir kürzlich den Code in einem Open Source-Projekt ansah, stellte ich fest, dass # Pragma-Programme an vielen Stellen verwendet werden. Daher habe ich den Google-Lehrer gefragt und die allgemeine Verwendung von vorkompilierten # Pragma-Anweisungen zusammengefasst. Jetzt werde ich sie mit Ihnen teilen.

1. #pragma die am häufigsten verwendete Methode

1. #progma pack (n)

1> Funktion:

Verwenden Sie die Vorkompilierungsanweisung #progma pack, um den Standardwert des Compilers zu ändern (nicht absolut, einige Compiler können nur die feste Datenausrichtung verwenden).

2> Beschreibung

In den meisten Fällen berücksichtigen wir beim Schreiben von Programmen keine Ausrichtungsprobleme, da der Compiler die richtige Strategie für uns auswählt. Die meisten Compiler verwenden standardmäßig die Vier-Byte-Ausrichtung.

Sie können ein Programm sehen, um zu verstehen:

Verfahren A:

#include <stdio.h>

Struktur A.

{

    int a;

    char b;

    kurz c;   

};

int main ()

{

    int d;

    d = Größe von (Struktur A);

    printf ("theleng =% d \ n", d);

     return 0;

}}

Hinweis:

(1) Im Allgemeinen verwenden wir 32-Bit-Prozessoren, und die Standardausrichtungsbyte-Nummer des VC-Compilers beträgt 4 Byte. Unter gcc ist standardmäßig der größte Variablentyp in der Struktur byteorientiert.

Struktur A enthält ein int mit einer Länge von 4 Bytes, ein Zeichen mit einer Länge von 1 Byte und kurze Daten mit einer Länge von 2 Bytes. Der von A verwendete Speicherplatz sollte also 7 Bytes betragen. Aber weil der Compiler die Datenelemente im Raum ausrichten muss. Verwenden Sie also den Wert für sizeof (strcut A) von 8 "a belegt 4 Bytes, b belegt ein Byte und c belegt zwei Bytes, sodass der Compiler b und C in 4 Bytes setzt, sodass der Strukturkörper A 8 Bytes belegt."

(2) Nun diskutieren wir die Vorteile der Byte-Ausrichtung:

Der Speicherplatz in modernen Computern ist nach Bytes unterteilt. Theoretisch scheint der Zugriff auf einen beliebigen Variablentyp von einer beliebigen Adresse aus zu beginnen. Die tatsächliche Situation besteht jedoch darin, dass beim Zugriff auf eine bestimmte Variable häufig auf einen bestimmten Speicher zugegriffen wird Adresse. Dies Alle Datentypen müssen nach bestimmten Regeln im Raum angeordnet werden, anstatt nacheinander angeordnet zu werden. Dies ist eine Ausrichtung

 

Die Rolle und der Grund der Ausrichtung: Die Verarbeitung des Speicherplatzes durch verschiedene Hardwareplattformen ist sehr unterschiedlich. Einige Plattformen können nur von bestimmten Adressen auf bestimmte Datentypen zugreifen. Andere Plattformen haben diese Situation möglicherweise nicht, aber am häufigsten kommt es zu einem Verlust der Zugriffseffizienz, wenn der Datenspeicher nicht gemäß den Anforderungen der Plattform ausgerichtet ist

 

Beispielsweise beginnen einige Plattformen jedes Mal mit einer geraden Adresse. Wenn ein int-Typ (unter der Annahme eines 32-Bit-Systems) am Anfang der geraden Adresse gespeichert wird, kann ein Lesezyklus gelesen werden, und wenn er am gespeichert wird ungerade Adresse, An einigen Stellen kann es 2 Lesezyklen dauern und die hohen und niedrigen Bytes der beiden Leseergebnisse zusammenfügen, um die int-Daten zu erhalten. Offensichtlich ist die Leseeffizienz stark gesunken. Dies ist auch ein Spiel zwischen Raum und Zeit

3> Wie benutzt man?

Anwendungsbeispiele:
#pragma pack (push) // Den vorherigen Ausrichtungsstatus speichern, push dient dazu, den vorherigen Ausrichtungsstatus auf den Stapel zu verschieben  
#pragma pack (1) // Geben Sie den neuen Ausrichtungsstatus an, 1 Byte
// definieren Sie die Struktur von  
// …………  
#pragma pack (pop) // Pop den Stapel und stelle den vorherigen Ausrichtungsstatus wieder her

Jetzt ändern wir das Programm gerade:

Verfahren B:

#include <stdio.h>

 

#pragma pack (push)

# Pragma Pack (1)

 

Struktur A.

{

    int a;

    char b;

    kurz c;   

};

#pragma pack (pop);

int main ()

{

    int d;

    d = Größe von (Struktur A);

    printf ("theleng =% d \ n", d);

     return 0;

}}

Zu diesem Zeitpunkt belegt Struktur A insgesamt 7 Bytes, da sie durch ein Byte ausgerichtet ist.

2. # Pragma-Nachricht ("String-Konstante")

1> Funktion:

Wenn der Compiler auf diese Anweisung stößt, druckt er den Nachrichtentext im Kompilierungsausgabefenster

2> Beschreibung:

Wenn wir im Programm viele Makros definieren, um die Quellcodeversion zu steuern, vergessen wir möglicherweise, ob wir diese Makros richtig eingestellt haben. Derzeit können wir diese Anweisung verwenden, um beim Kompilieren zu überprüfen.

3> Wie benutzt man?
# Pragma-Nachricht ("Makro aktiviert!")

Hinweis: Hier gibt es kein Semikolon nach message ().

3. # Pragma einmal

1> Funktion:

Fügen Sie diese Anweisung einfach ganz am Anfang der Header-Datei hinzu, um sicherzustellen, dass die Header-Datei einmal kompiliert wird

2> Hinweis: Der Unterschied zwischen #pragma einmal und #ifndef

(1) Ähnlichkeiten:

Um zu vermeiden, dass dieselbe Datei mehrmals enthalten ist, gibt es keinen großen Unterschied zwischen dem # ifndef-Modus und dem # pragma-Einmalmodus (vorausgesetzt, der Compiler kann beide Modi gleichzeitig unterstützen).

(2) So verwenden Sie beide:

Methode eins:

#ifndef __TIGER_H__

#define __TIGER_H__

……… .// Einige Erklärungen

#endif

Methode Zwei:

#pragma einmal

……… // Einige Deklarationserklärungen

(3) Der Unterschied zwischen den beiden:

Die Methode von #ifndef basiert auf der Tatsache, dass die Makronamen nicht in Konflikt geraten können. Dies stellt nicht nur sicher, dass dieselbe Datei nicht mehrmals eingeschlossen wird, sondern auch, dass zwei Header-Dateien mit demselben Inhalt nicht versehentlich gleichzeitig eingeschlossen werden . Der Nachteil ist natürlich, dass wenn die Makronamen verschiedener Header-Dateien versehentlich "abstürzen", die Header-Dateien möglicherweise existieren, der Compiler jedoch darauf besteht, dass die Deklaration nicht gefunden wird.

#pragma einmal wird vom Compiler garantiert: Dieselbe Datei wird nicht mehrmals eingeschlossen. Beachten Sie, dass sich dieselbe hier erwähnte Datei auf eine physische Datei bezieht, nicht auf zwei Dateien mit demselben Inhalt. Der Vorteil ist, dass Sie nicht mehr über einen Makronamen nachdenken müssen und es natürlich keine merkwürdigen Probleme mehr gibt, die durch Kollisionen von Makronamen verursacht werden. Der entsprechende Nachteil besteht darin, dass diese Methode bei mehreren Kopien einer Header-Datei nicht garantieren kann, dass sie nicht wiederholt aufgenommen werden. Verglichen mit dem Problem "Deklaration kann nicht gefunden werden", das durch Kollisionen von Makronamen verursacht wird, sind wiederholte Einschlüsse natürlich leichter zu finden und zu korrigieren.

Für #pragmaonce kann laut MSDN verhindert werden, dass eine Datei mehrmals enthalten ist. Im Vergleich zum Dateischutz in Form von #ifndef #define #endif ist ersteres plattformabhängig und weist eine schlechte Portabilität auf. Es ist jedoch effizienter, da die enthaltene Datei nicht geöffnet werden muss, um festzustellen, ob die Datei enthalten ist. Natürlich erledigt das System diese Arbeit für uns. Letzteres hat den Vorteil, dass es sich um eine sprachbezogene Funktion handelt, sodass die Portabilität gut ist. Wenn Sie jedoch eine Datei einschließen, öffnen Sie die Datei nur und beurteilen Sie, ob die Datei enthalten ist, je nachdem, ob das Schutzmakro der Datei definiert wurde. Der Wirkungsgrad ist relativ gering. Natürlich kann der Programmierer bei #include auch beurteilen, ob das Schutzmakro der einzuschließenden Datei definiert wurde, um zu entscheiden, ob die Datei aufgenommen werden soll. Ähnlich dem folgenden Code:

#ifndef FILE_H_

#Include "file.h"

#endif

Dies kann zu einer höheren Effizienz führen und die Portabilität sicherstellen. Die Abhängigkeit zwischen Dateien ist jedoch hoch. Wenn das Schutzmakro einer Datei geändert wird, müssen alle Dateien, die diese Datei im obigen Format enthalten, geändert werden. Im Gegensatz zur Idee der Modularität.

2. #pragma einige andere Methoden

1. Der Parameter #pragma ist code_seg.

1> Format: 

#pragma code_seg ([[{push | pop},] [bezeichner,]] ["segmentname" [, "segmentklasse"])

2> Funktion:

Es kann das Codesegment des Funktionscodes im Programm festlegen, das bei der Entwicklung des Treibers verwendet wird

3> Beschreibung:

Diese Anweisung wird verwendet, um den Abschnitt anzugeben, in dem die Funktion in der OBJ-Datei gespeichert ist. Um die OBJ-Datei zu beobachten, können Sie das mit VC gelieferte Befehlszeilenprogramm dumpbin verwenden. Der Standardspeicherabschnitt der Funktion in der OBJ-Datei ist der Textabschnitt, wenn code_seg keine Parameter akzeptiert. Die Funktion wird im Textabschnitt gespeichert. push (optionaler Parameter) Legen Sie einen Datensatz auf den Stapel des internen Compilers. Der optionale Parameter kann ein Bezeichner oder ein Abschnittsname sein. pop (optionaler Parameter) Pop einen Datensatz von der Oberseite des Stapels. Der Datensatz kann eine Kennung oder ein Abschnittsname sein. Bezeichner (optionaler Parameter) Wenn die Push-Anweisung verwendet wird, wird dem auf den Stapel geschobenen Datensatz ein Bezeichner zugewiesen. Wenn der Bezeichner gelöscht wird, wird der Datensatz im zugehörigen Stapel aus dem Stapel entfernt. "Segmentname" (optionaler Parameter) steht für den Namen des Abschnitts, in dem die Funktion gespeichert ist

3> Beispiel:

// Standardmäßig werden Funktionen im Textabschnitt gespeichert

void func1 () {// in .text gespeichert

}}

 

// Speichern Sie die Funktion im Abschnitt .my_data1

#pragma code_seg (". my_data1")

void func2 () {// in my_data1 gespeichert

}}

 

// r1 ist der Bezeichner, setzen Sie die Funktion in den Abschnitt .my_data2

#pragma code_seg (push, r1, ".my_data2")

void func3 () {// in my_data2 gespeichert

}}

 

int main () {

}}

2. # pragma hdrstop

1> Funktion:

Gibt an, dass die vorkompilierte Header-Datei hier endet. Die folgenden Header-Dateien sind nicht vorkompiliert. BCB kann die Header-Dateien vorkompilieren, um die Verknüpfung zu beschleunigen. Wenn jedoch alle Header-Dateien vorkompiliert sind, kann dies auch dauern Verwenden Sie diese Option, um einige Header-Dateien auszuschließen. 

Manchmal gibt es Abhängigkeiten zwischen Einheiten, zum Beispiel hängt Einheit A von Einheit B ab, daher muss Einheit B vor Einheit A kompiliert werden. Sie können den Start von #pragma verwenden, um die Kompilierungspriorität anzugeben. Wenn das Paket #pragma (smart_init) verwendet wird, wird BCB entsprechend der Priorität kompiliert. 
3. # Pragma-Warnung

1> Funktion:

Diese Anweisung ermöglicht es, das Verhalten von Compiler-Warnmeldungen selektiv zu ändern

2> Befehlsformat:

#pragma warning (Warnspezifizierer: Warnnummernliste [; Warnspezifizierer: Warnnummernliste ...]

# Pragma-Warnung (drücken Sie [, n])

# Pragma Warnung (Pop)

3> Die wichtigsten verwendeten Warnungen lauten wie folgt:

einmal: Zeigt die Meldung nur einmal an (Warnung / Fehler usw.)

Standard: Setzt das Warnverhalten des Compilers auf den Standardzustand zurück

1,2,3,4: Vier Warnstufen

Deaktivieren: Verbietet die angegebene Warnmeldung

Fehler: Melden Sie die angegebene Warnmeldung als Fehler

Wenn Sie die obige Erklärung nicht sehr gut verstehen, können Sie sich auf das folgende Beispiel und die folgende Erklärung beziehen

# Pragma-Warnung (deaktivieren: 4507 34; einmal: 4385; Fehler: 164) 

Gleichwertig: 

#pragma warning (disable: 4507 34) // Keine Warnmeldungen 4507 und 34 anzeigen 

#pragma warning (einmal: 4385) // Warnmeldung Nr. 4385 wird nur einmal gemeldet 

#pragma warning (Fehler: 164) // Betrachten Sie die Warnmeldung 164 als Fehler. 

Gleichzeitig unterstützt diese Pragma-Warnung auch das folgende Format: 

# Pragma-Warnung (drücken Sie [, n]) 

# Pragma Warnung (Pop) 

Hier steht n für eine Warnstufe (1 --- 4). 

#pragma warning (push) Speichert den vorhandenen Warnstatus aller Warnmeldungen. 

#pragma warning (push, n) speichert den vorhandenen Warnstatus aller Warnmeldungen und setzt die globale Warnung 

Der Pegel ist auf n eingestellt.  

#pragma warning (pop) Fügt die letzte Warnmeldung in den Stapel ein, die zwischen Stapeln und Poppen erfolgt 

Alle Änderungen werden abgebrochen. Z.B: 

# Pragma Warnung (drücken) 

# Pragma-Warnung (deaktivieren: 4705) 

# Pragma-Warnung (deaktivieren: 4706) 

# Pragma-Warnung (deaktivieren: 4707) 

# Pragma Warnung (Pop)

Speichern Sie am Ende dieses Codes alle Warnmeldungen (einschließlich 4705, 4706 und 4707).

Wenn Sie Standard-C ++ für die Programmierung verwenden, werden häufig viele Warnmeldungen angezeigt, und diese Warnmeldungen sind unnötige Eingabeaufforderungen.

Wir können also die # Pragma-Warnung (deaktivieren: 4786) verwenden, um diese Art von Warnung zu deaktivieren

Wenn Sie ADO in vc verwenden, erhalten Sie auch unnötige Warnmeldungen. Zu diesem Zeitpunkt können wir bestehen

#pragma warning (disable: 4146), um diese Art von Warnmeldung zu entfernen

4. # Pragma Kommentar (...)

1> Funktion:

Diese Anweisung fügt einen Kommentardatensatz in eine Objektdatei oder eine ausführbare Datei ein.

2> Format:

#pragma comment ("Kommentartyp" [, Kommentarzeichenfolge])

Kommentartyp: Kann als einer von fünf vordefinierten Bezeichnern angegeben werden

Die fünf vordefinierten Bezeichner sind:

(1) Compiler: Geben Sie die Versionsnummer und den Namen des Compilers in die Zieldatei ein. Dieser Kommentardatensatz wird vom Compiler ignoriert. Wenn Sie den Kommentarstring-Parameter für den Datensatztyp angeben, generiert der Compiler eine Warnung

Zum Beispiel: #pragma comment (Compiler)

(2) exestr: Fügen Sie den Kommentarkommentar-Parameter in die Zieldatei ein. Diese Zeichenfolge wird beim Verknüpfen in die ausführbare Datei eingefügt. Wenn das Betriebssystem die ausführbare Datei lädt, wird die Parameterzeichenfolge nicht in den Speicher geladen. Die Zeichenfolge wird jedoch geladen kann von Programmen wie dumpbin gefunden und ausgedruckt werden. Mit dieser Kennung können Sie Informationen wie die Versionsnummer in die ausführbare Datei einbetten!

(3) lib: Dies ist ein sehr häufig verwendetes Schlüsselwort, um eine Bibliotheksdatei mit der Zieldatei zu verknüpfen

Häufig verwendete lib-Schlüsselwörter können uns helfen, eine Verbindung zu einer Bibliotheksdatei herzustellen. 

Z.B:

#pragma comment (lib, "user32.lib") 

Mit diesem Befehl wird diesem Projekt die Bibliotheksdatei user32.lib hinzugefügt

Linker: Fügen Sie eine Link-Option in die Zieldatei ein. Sie können diesen Befehl anstelle der Befehlszeile oder in der Entwicklungsumgebung verwenden

       Um die Verknüpfungsoption festzulegen, können Sie die Option / include angeben, um die Aufnahme eines bestimmten Objekts zu erzwingen. Beispiel:

      #pragma comment (Linker, "/ include: __ mySymbol")

Sie können die folgenden Linkoptionen im Programm festlegen

/ DEFAULTLIB

/EXPORT

/EINSCHLIESSEN

/VERSCHMELZEN

/SEKTION

Diese Optionen werden hier nicht einzeln erläutert. Weitere Informationen finden Sie in msdn!

5. # Pragma-Ressource "*. Dfm"

1> Funktion:

Dies bedeutet, dass die Ressourcen in der * .dfm-Datei zum Projekt hinzugefügt werden. * .dfm enthält die Definition des Erscheinungsbilds des Formulars.
 

Ich denke du magst

Origin blog.csdn.net/xiaolei251990/article/details/83783194
Empfohlen
Rangfolge