Namensräume
Varianten
Aktionen

Steuerung des implementierungsdefinierten Verhaltens

Von cppreference.com

Das implementierungsdefinierte Verhalten wird durch die Direktive #pragma gesteuert.

Inhalt

[bearbeiten] Syntax

#pragma pragma_params (1)
_Pragma ( string-literal ) (2) (seit C99)
1) Verhält sich implementierungsdefiniert (es sei denn, pragma_params ist eines der unten aufgeführten Standard-Pragmas).
2) Entfernt das Kodierungspräfix (falls vorhanden), die äußeren Anführungszeichen sowie führende/nachfolgende Leerzeichen aus string-literal, ersetzt jedes \" durch " und jedes \\ durch \, tokenisiert dann das Ergebnis (wie in Übersetzungsphase 3) und verwendet dann das Ergebnis, als wäre es die Eingabe für #pragma in (1).

[bearbeiten] Erklärung

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

[bearbeiten] 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 es den Compiler, dass das Programm die Gleitkomma-Umgebung abgreift oder modifiziert, was bedeutet, dass Optimierungen, die Flag-Tests und Modusänderungen untergraben könnten (z. B. globale gemeinsame Teil-Ausdrücke, Code-Bewegung und Konstantenfaltung), verboten sind. Der Standardwert ist implementierungsdefiniert, normalerweise OFF.
2) Erlaubt das *Zusammenfassen* von Gleitkomma-Ausdrücken, d. h. Optimierungen, die Rundungsfehler und Gleitkomma-Ausnahmen auslassen, die beobachtet würden, wenn der Ausdruck exakt wie geschrieben ausgewertet würde. Erlaubt beispielsweise die Implementierung von (x * y) + z mit einer einzigen Fused Multiply-Add CPU-Instruktion. Der Standardwert ist implementierungsdefiniert, normalerweise ON.
3) Informiert den Compiler, dass die Multiplikation, Division und der Absolutwert 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)]/(u2
+v2
)
und |x+iy| = x2
+y2
, trotz der Möglichkeit eines Zwischenüberlaufs. Mit anderen Worten, der Programmierer garantiert, dass der Wertebereich der an diese Funktionen übergebenen Werte begrenzt ist. Der Standardwert ist OFF.

Hinweis: Compiler, die diese Pragmas nicht unterstützen, bieten möglicherweise äquivalente Compiler-Optionen an, wie z. B. gcc's -fcx-limited-range und -ffp-contract.

[bearbeiten] Nicht-Standard-Pragmas

[bearbeiten] #pragma once

#pragma once ist ein nicht-standardmäßiges Pragma, das von der überwiegenden Mehrheit moderner Compiler unterstützt wird. Wenn es in einer Header-Datei erscheint, zeigt es an, dass sie nur einmalig geparst werden soll, auch wenn sie (direkt oder indirekt) mehrfach in derselben Quelldatei enthalten ist.

Der Standardansatz zur Verhinderung der mehrfachen Einbindung derselben Header-Datei ist die Verwendung von Include Guards.

#ifndef LIBRARY_FILENAME_H
#define LIBRARY_FILENAME_H
// contents of the header
#endif /* LIBRARY_FILENAME_H */

So dass alle außer der ersten Einbindung des Headers in einer beliebigen Ü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 wieder angetroffen wird, solange der Guard noch definiert ist (siehe z. B. gcc).

Mit #pragma once erscheint derselbe Header wie

#pragma once
// contents of the header

Im Gegensatz zu Header Guards macht dieses Pragma es unmöglich, denselben Makronamen versehentlich in mehr als einer Datei zu verwenden. Andererseits kann dies, da mit #pragma once Dateien basierend auf ihrer Dateisystemidentität ausgeschlossen werden, nicht vor dem zweimaligen Einbinden eines Headers schützen, wenn dieser an mehr als einem Ort in einem Projekt existiert.

[bearbeiten] #pragma pack

Diese Pragma-Familie steuert die maximale Ausrichtung für nachfolgend 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) Pusht den Wert der aktuellen Ausrichtung auf einen internen Stack.
4) Pusht den Wert der aktuellen Ausrichtung auf den internen Stack und setzt dann die aktuelle Ausrichtung auf den Wert arg.
5) Poppt 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 keine Struktur übermäßig ausrichten.

Siehe spezifische Details für GCC und MSVC.

[bearbeiten] Referenzen

  • 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

[bearbeiten] Siehe auch

C++ Dokumentation für Steuerung des implementierungsdefinierten Verhaltens

[bearbeiten] Externe Links

1.  C++ Pragmas in Visual Studio 2019
2.  Von GCC akzeptierte Pragmas
3.  Einzelne Pragma-Beschreibungen und Standard-Pragmas in IBM AIX XL C 16.1
4.  Anhang B. Pragmas im Sun Studio 11 C++ User's Guide
5.  Intel C++ Compiler Pragmas
6.  HP aCC Compiler Pragmas