Namespaces
Variants

Implementation defined behavior control

From cppreference.net

Implementierungsdefiniertes Verhalten wird durch die #pragma -Direktive gesteuert.

Inhaltsverzeichnis

Syntax

#pragma pragma_params (1)
_Pragma ( string-literal ) (2) (seit C99)
1) Verhält sich auf implementierungsdefinierte Weise (sofern pragma_params nicht einer der unten gezeigten Standard-Pragmas entspricht).
2) Entfernt das Kodierungspräfix (falls vorhanden), die äußeren Anführungszeichen und führende/abschließende Leerzeichen von string-literal , ersetzt jedes \" durch " und jedes \\ durch \ , tokenisiert dann das Ergebnis (wie in Übersetzungsphase 3 ) und verwendet das Ergebnis dann als wäre es die Eingabe für #pragma in (1) .

Erklärung

Die Pragma-Direktive steuert implementierungsspezifisches Verhalten des Compilers, wie das Deaktivieren von Compiler-Warnungen oder das Ändern von Ausrichtungsanforderungen. Jedes nicht erkannte Pragma wird ignoriert.

Standard-Pragmas

Die folgenden drei Pragmas sind durch den Sprachstandard definiert:

#pragma STDC FENV_ACCESS arg (1) (seit C99)
#pragma STDC FP_CONTRACT arg (2) (seit C99)
#pragma STDC CX_LIMITED_RANGE arg (3) (seit C99)

wobei arg entweder ON oder OFF oder DEFAULT ist.

1) Wenn auf ON gesetzt, informiert dies den Compiler, dass das Programm auf die Gleitkommaumgebung zugreifen oder sie ändern wird, was bedeutet, dass Optimierungen, die Flag-Tests und Modusänderungen untergraben könnten (z.B. globale Common Subexpression Elimination, Code Motion und Constant Folding), untersagt sind. Der Standardwert ist implementierungsdefiniert, üblicherweise OFF .
2) Erlaubt die Kontrahierung von Gleitkommaausdrücken, also Optimierungen, die Rundungsfehler und Gleitkommaausnahmen auslassen, die beobachtet würden, wenn der Ausdruck exakt wie geschrieben ausgewertet würde. Erlaubt beispielsweise die Implementierung von ( x * y ) + z mit einer einzelnen Fused-Multiply-Add-CPU-Anweisung. Der Standardwert ist implementierungsdefiniert, üblicherweise ON .
3) Informiert den Compiler, dass Multiplikation, Division und Absolutbetrag von komplexen Zahlen vereinfachte mathematische Formeln verwenden dürfen (x+iy)×(u+iv) = (xu-yv)+i(yu+xv) , (x+iy)/(u+iv) = [(xu+yv)+i(yu-xv)]/(u 2
+v 2
)
, und |x+iy| = x 2
+y 2
, trotz der Möglichkeit von Zwischenüberläufen. Mit anderen Worten garantiert der Programmierer, dass der Wertebereich der an diese Funktionen übergebenen Werte begrenzt ist. Der Standardwert ist OFF .

Hinweis: Compiler, die diese Pragma nicht unterstützen, können äquivalente Kompilierzeit-Optionen bereitstellen, wie z.B. gcc's -fcx-limited-range und -ffp-contract .

Nicht standardkonforme Pragmas

#pragma once

#pragma once ist eine nicht standardisierte Pragma-Direktive, die von der überwiegenden Mehrheit moderner Compiler unterstützt wird. Wenn sie in einer Header-Datei erscheint, zeigt sie an, dass sie nur einmal geparst werden soll, selbst wenn sie (direkt oder indirekt) mehrmals in derselben Quelldatei eingebunden wird.

Der Standardansatz zur Vermeidung mehrfacher Einbindung derselben Header-Datei erfolgt durch Verwendung von Include Guards :

#ifndef LIBRARY_FILENAME_H
#define LIBRARY_FILENAME_H
// Inhalt der Header-Datei
#endif /* LIBRARY_FILENAME_H */

Damit alle bis auf die erste Einbindung der Header-Datei in jeder Übersetzungseinheit von der Kompilierung ausgeschlossen werden. Alle modernen Compiler merken sich, dass eine Header-Datei einen Include-Guard verwendet und parsen die Datei nicht erneut, wenn sie erneut auftaucht, solange der Guard noch definiert ist (siehe z.B. gcc ).

Mit #pragma once erscheint derselbe Header als

#pragma once
// Inhalt der Header-Datei

Im Gegensatz zu Header-Guards macht dieses Pragma es unmöglich, fälschlicherweise denselben Makronamen in mehr als einer Datei zu verwenden. Andererseits, da mit #pragma once Dateien basierend auf ihrer Dateisystem-Identität ausgeschlossen werden, kann dies nicht davor schützen, einen Header zweimal einzubinden, wenn er an mehr als einer Stelle in einem Projekt existiert.

#pragma pack

Diese Familie von Pragmas steuert die maximale Ausrichtung für anschließend definierte Struktur- und Union-Mitglieder.

#pragma pack( arg ) (1)
#pragma pack() (2)
#pragma pack(push) (3)
#pragma pack(push, arg ) (4)
#pragma pack(pop) (5)

wobei arg eine kleine Zweierpotenz ist und die neue Ausrichtung in Bytes angibt.

1) Setzt die aktuelle Ausrichtung auf den Wert arg .
2) Setzt die aktuelle Ausrichtung auf den Standardwert (angegeben durch eine Kommandozeilenoption).
3) Legt den Wert der aktuellen Ausrichtung auf einen internen Stapel.
4) Legt den Wert der aktuellen Ausrichtung auf dem internen Stack ab und setzt dann die aktuelle Ausrichtung auf den Wert arg .
5) Entfernt den obersten Eintrag vom internen Stack und setzt (stellt) dann die aktuelle Ausrichtung auf diesen Wert zurück.

#pragma pack kann die Ausrichtung einer Struktur verringern, kann jedoch eine Struktur nicht überausrichten.

Siehe auch spezifische Details für GCC und MSVC .

Referenzen

  • C23-Standard (ISO/IEC 9899:2024):
  • 6.10.6 Pragma directive (S.: TBD)
  • 6.10.9 Pragma operator (S.: TBD)
  • C17-Standard (ISO/IEC 9899:2018):
  • 6.10.6 Pragma-Direktive (S. 127)
  • 6.10.9 Pragma-Operator (S. 129)
  • C11-Standard (ISO/IEC 9899:2011):
  • 6.10.6 Pragma-Direktive (S. 174)
  • 6.10.9 Pragma-Operator (S. 178)
  • C99-Standard (ISO/IEC 9899:1999):
  • 6.10.6 Pragma-Direktive (S: 159)
  • 6.10.9 Pragma-Operator (S: 161-162)
  • C89/C90 Standard (ISO/IEC 9899:1990):
  • 3.8.6 Pragma-Direktive

Siehe auch

C++ Dokumentation für Implementierungsdefiniertes Verhalten Steuerung

Externe Links

1. C++-Pragmas in Visual Studio
2. Pragmas von GCC akzeptiert
3. Einzelne Pragmabeschreibungen und Standard-Pragmas in IBM AIX XL C 16.1
4. Anhang B. Pragmas im Sun Studio 11 C++ Benutzerhandbuch
5. Intel C++ Compiler-Pragmas
6. HP aCC Compiler-Pragmas