@smwikipedia meinst du einige Pragmas überleben? #pragma einmal ist eine Präprozessor-Direktive, aber #pragma pack ist eine Compiler-Direktive
Lewis Kelsey
Antworten:
66
#pragma ist für Compiler-Direktiven gedacht, die maschinenspezifisch oder betriebssystemspezifisch sind, dh der Compiler wird angewiesen, etwas zu tun, eine Option festzulegen, Maßnahmen zu ergreifen, einige Standardeinstellungen zu überschreiben usw., die möglicherweise für alle Maschinen und den Betrieb gelten oder nicht Systeme.
"Das kann für alle Maschinen und Betriebssysteme gelten oder nicht." - und verschiedene Compiler auf derselben Maschine. Und was auf verschiedenen Compilern unterschiedliche Bedeutungen haben könnte.
Steve Jessop
53
#pragma wird verwendet, um etwas Implementierungsspezifisches in C zu tun, dh für den aktuellen Kontext pragmatisch und nicht ideologisch dogmatisch zu sein.
Die, die ich regelmäßig verwende, ist der, #pragma pack(1)bei dem ich versuche, bei eingebetteten Lösungen mit Arrays von Strukturen, die sonst zu einer 8-Byte-Ausrichtung führen würden, mehr aus meinem Speicherplatz herauszuholen.
Schade, dass wir noch keine haben #dogma. Das würde Spaß machen ;)
@ Pacerier, normalerweise nicht. Gemäß den Jalfs-Kommentaren werden Daten, die an einer 4-Byte-Grenze für 32-Bit-Prozessoren oder einer 8-Byte-Grenze für 64-Bit-Prozessoren ausgerichtet sind, normalerweise in einer einzigen Operation geladen und gespeichert. Daten, die an kleineren Grenzen ausgerichtet sind, benötigen mehrere Vorgänge zum Laden oder Speichern. Das ist langsamer.
SmacL
35
Ich würde generell versuchen, die Verwendung von #pragmas möglichst zu vermeiden, da sie extrem compilerabhängig und nicht portabel sind. Wenn Sie sie tragbar verwenden möchten, müssen Sie jedes Pragma mit einem #if/ #endifPaar umgeben. GCC rät von der Verwendung von Pragmas ab und unterstützt nur einige davon aus Gründen der Kompatibilität mit anderen Compilern. GCC hat andere Möglichkeiten, die gleichen Dinge zu tun, für die andere Compiler Pragmas verwenden.
So stellen Sie beispielsweise sicher, dass eine Struktur in MSVC dicht gepackt ist (dh keine Auffüllung zwischen Mitgliedern):
Wenn ich also den GCC-Code auf MSVC kompilieren möchte und die Struktur packen muss, wie genau mache ich das?
SmacL
2
Für gcc ist es struct __attribute__((__packed__)) PackedStructure
Laurent Debricon
#pragma einmal ist nicht realistisch "compilerabhängig und nicht portabel". Es ist auf alle wichtigen Plattform unterstützt und viele nicht-großen Plattformen .. en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon
1
Beachten Sie, dass sowohl C99 als auch C11 (C11) §6.10.6 Pragma-Anweisungen und ¶1 enthalten. Jedes solche Pragma, das von der Implementierung nicht erkannt wird, wird ignoriert. Sogar C90 sagt das, obwohl es in Abschnitt §6.8.6 war. (Dies macht GCC nicht konform, wenn es ausgeführt wird, hackwenn es auf ein Pragma stößt, das es nicht erkennt, wie es es vor sehr, sehr langer Zeit getan hat - siehe #pragmaund GCC usw.)
Jonathan Leffler
15
Wenn Sie #pragma onceoben in Ihre Header-Datei einfügen, wird sichergestellt, dass sie nur einmal enthalten ist. Beachten Sie, dass dies #pragma oncekein Standard-C99 ist, sondern von den meisten modernen Compilern unterstützt wird.
Eine Alternative ist die Verwendung Wachen sind (zB #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)
Was ich #pragmadenke, ist eine Direktive, in der, wenn Sie möchten, dass der Code ortsspezifisch ist. Sagen Sie eine Situation, in der der Programmzähler von der spezifischen Adresse lesen soll, an der der ISR geschrieben ist, dann können Sie den ISR an diesem Ort mit #pragma vector=ADC12_VECTORund gefolgt von angeben Interrupt dreht den Namen und seine Beschreibung
Mein bester Rat ist, sich die Dokumentation Ihres Compilers anzusehen, da Pragmas per Definition implementierungsspezifisch sind. In eingebetteten Projekten habe ich sie beispielsweise verwendet, um Code und Daten in verschiedenen Abschnitten zu suchen oder Interrupt-Handler zu deklarieren. dh:
#pragma code BANK1#pragma data BANK2#pragma INT3 TimerHandler
Alle Pragmas sind implementierungsspezifisch - mit Ausnahme der Pragmas #pragma STDC ..., die plattformübergreifend standardisiert sind (zusätzlich zu C99).
Jonathan Leffler
4
Alle obigen Antworten sind nette Erklärungen, #pragmaaber ich wollte ein kleines Beispiel hinzufügen
Ich möchte nur ein Beispiel erläutern simple OpenMP example, das einige Verwendungsmöglichkeiten für #pragmaseine Arbeit demonstriert
OpenMp brieflyist eine Implementierung für die parallele Programmierung von Shared-Memory mit mehreren Plattformen (dann können wir sagen, es ist machine-specificoder operating-system-specific)
Gehen wir zum Beispiel
#include<stdio.h>#include<omp.h>// compile with: /openmpint main(){#pragma omp parallel num_threads(4){int i = omp_get_thread_num();
printf_s("Hello from thread %d\n", i);}}
die Ausgabe ist
Hello from thread 0Hello from thread 1Hello from thread 2Hello from thread 3Note that the order of output can vary on different machines.
Jetzt lass mich dir sagen, was #pragma...
Es weist das Betriebssystem an, den Codeblock auf 4 Threads auszuführen
Dies ist nur einer von many many applicationseuch, der mit dem Kleinen etwas anfangen kann#pragma
#pragma startup ist eine Direktive, mit der eine Funktion vor der Hauptfunktion und eine andere Funktion nach der Hauptfunktion aufgerufen wird, z
#pragma startup func1
#pragma exit func2
Hier func1läuft vorher mainund func2läuft danach.
HINWEIS: Dieser Code funktioniert nur im Turbo-C-Compiler. Um diese Funktionalität in GCC zu erreichen, können Sie Folgendes deklarieren func1und func2mögen:
Um es zusammenzufassen, #pragmaweist er den Compiler an, Dinge zu tun. Hier sind einige Möglichkeiten, wie ich es benutze:
#pragmakann verwendet werden, um Compiler-Warnungen zu ignorieren. Um beispielsweise GCC wegen impliziter Funktionsdeklarationen zum Schweigen zu bringen, können Sie Folgendes schreiben:
#pragma onceWenn diese Header-Datei oben in eine Header-Datei geschrieben wird, wird sie einmal eingefügt. libportableprüft auf Pragma einmal Unterstützung.
#pragma
Die Richtlinie überlebt die Vorverarbeitungsphase. Im Gegensatz zu#include
und#define
.Antworten:
#pragma
ist für Compiler-Direktiven gedacht, die maschinenspezifisch oder betriebssystemspezifisch sind, dh der Compiler wird angewiesen, etwas zu tun, eine Option festzulegen, Maßnahmen zu ergreifen, einige Standardeinstellungen zu überschreiben usw., die möglicherweise für alle Maschinen und den Betrieb gelten oder nicht Systeme.Siehe msdn für weitere Informationen.
quelle
#pragma
wird verwendet, um etwas Implementierungsspezifisches in C zu tun, dh für den aktuellen Kontext pragmatisch und nicht ideologisch dogmatisch zu sein.Die, die ich regelmäßig verwende, ist der,
#pragma pack(1)
bei dem ich versuche, bei eingebetteten Lösungen mit Arrays von Strukturen, die sonst zu einer 8-Byte-Ausrichtung führen würden, mehr aus meinem Speicherplatz herauszuholen.Schade, dass wir noch keine haben
#dogma
. Das würde Spaß machen ;)quelle
pragma(1)
Verbessert die Geschwindigkeit nicht auch wirklich? Siehe stackoverflow.com/questions/3318410/…Ich würde generell versuchen, die Verwendung von #pragmas möglichst zu vermeiden, da sie extrem compilerabhängig und nicht portabel sind. Wenn Sie sie tragbar verwenden möchten, müssen Sie jedes Pragma mit einem
#if
/#endif
Paar umgeben. GCC rät von der Verwendung von Pragmas ab und unterstützt nur einige davon aus Gründen der Kompatibilität mit anderen Compilern. GCC hat andere Möglichkeiten, die gleichen Dinge zu tun, für die andere Compiler Pragmas verwenden.So stellen Sie beispielsweise sicher, dass eine Struktur in MSVC dicht gepackt ist (dh keine Auffüllung zwischen Mitgliedern):
So würden Sie in GCC dasselbe tun:
Der GCC-Code ist portabler, denn wenn Sie ihn mit einem Nicht-GCC-Compiler kompilieren möchten, müssen Sie nur etwas tun
#define __attribute__(x)
Wenn Sie den MSVC-Code portieren möchten, müssen Sie jedes Pragma mit einem
#if
/#endif
pair umgeben. Nicht hübsch.quelle
struct __attribute__((__packed__)) PackedStructure
hack
wenn es auf ein Pragma stößt, das es nicht erkennt, wie es es vor sehr, sehr langer Zeit getan hat - siehe#pragma
und GCC usw.)Wenn Sie
#pragma once
oben in Ihre Header-Datei einfügen, wird sichergestellt, dass sie nur einmal enthalten ist. Beachten Sie, dass dies#pragma once
kein Standard-C99 ist, sondern von den meisten modernen Compilern unterstützt wird.Eine Alternative ist die Verwendung Wachen sind (zB
#ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */
)quelle
Was ich
#pragma
denke, ist eine Direktive, in der, wenn Sie möchten, dass der Code ortsspezifisch ist. Sagen Sie eine Situation, in der der Programmzähler von der spezifischen Adresse lesen soll, an der der ISR geschrieben ist, dann können Sie den ISR an diesem Ort mit#pragma vector=ADC12_VECTOR
und gefolgt von angeben Interrupt dreht den Namen und seine Beschreibungquelle
Mein bester Rat ist, sich die Dokumentation Ihres Compilers anzusehen, da Pragmas per Definition implementierungsspezifisch sind. In eingebetteten Projekten habe ich sie beispielsweise verwendet, um Code und Daten in verschiedenen Abschnitten zu suchen oder Interrupt-Handler zu deklarieren. dh:
quelle
Alle obigen Antworten sind nette Erklärungen,
#pragma
aber ich wollte ein kleines Beispiel hinzufügenIch möchte nur ein Beispiel erläutern
simple OpenMP example
, das einige Verwendungsmöglichkeiten für#pragma
seine Arbeit demonstriertGehen wir zum Beispiel
die Ausgabe ist
Jetzt lass mich dir sagen, was
#pragma
...Es weist das Betriebssystem an, den Codeblock auf 4 Threads auszuführen
Dies ist nur einer von
many many applications
euch, der mit dem Kleinen etwas anfangen kann#pragma
Entschuldigung für die äußere Probe
OpenMP
quelle
Dies ist eine Präprozessoranweisung, mit der bestimmte Funktionen ein- oder ausgeschaltet werden können.
Es ist von zwei Arten
#pragma startup
,#pragma exit
und#pragma warn
.#pragma startup
ermöglicht es uns, Funktionen anzugeben, die beim Programmstart aufgerufen werden.#pragma exit
ermöglicht es uns, Funktionen anzugeben, die beim Beenden des Programms aufgerufen werden.#pragma warn
Weist den Computer an, jede Warnung zu unterdrücken oder nicht.Viele andere
#pragma
Stile können verwendet werden, um den Compiler zu steuern.quelle
#pragma startup
ist eine Direktive, mit der eine Funktion vor der Hauptfunktion und eine andere Funktion nach der Hauptfunktion aufgerufen wird, zHier
func1
läuft vorhermain
undfunc2
läuft danach.HINWEIS: Dieser Code funktioniert nur im Turbo-C-Compiler. Um diese Funktionalität in GCC zu erreichen, können Sie Folgendes deklarieren
func1
undfunc2
mögen:quelle
Um es zusammenzufassen,
#pragma
weist er den Compiler an, Dinge zu tun. Hier sind einige Möglichkeiten, wie ich es benutze:#pragma
kann verwendet werden, um Compiler-Warnungen zu ignorieren. Um beispielsweise GCC wegen impliziter Funktionsdeklarationen zum Schweigen zu bringen, können Sie Folgendes schreiben:Eine ältere Version von
libportable
macht dies portabel .#pragma once
Wenn diese Header-Datei oben in eine Header-Datei geschrieben wird, wird sie einmal eingefügt.libportable
prüft auf Pragma einmal Unterstützung.quelle