Namensräume
Varianten
Aktionen

Steuerung des implementierungsdefinierten Verhaltens

Von cppreference.com
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Implementierungsdefiniertes Verhalten wird durch die Direktive #pragma gesteuert.

Inhalt

[bearbeiten] Syntax

#pragma pragma-params (1)
_Pragma( string-literal ) (2) (seit C++11)
1) Verhält sich auf implementierungsdefinierte Weise.
2) Entfernt das L-Präfix (falls vorhanden), die äußeren Anführungszeichen und 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 ob es die Eingabe für #pragma in (1) wäre.

[bearbeiten] Erklärung

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

[bearbeiten] Nicht-Standard-Pragmas

Der ISO C++ Sprachstandard schreibt den Compilern keine Unterstützung für bestimmte Pragmas vor. Allerdings werden mehrere nicht-standardmäßige Pragmas von mehreren Implementierungen unterstützt.

[bearbeiten] #pragma STDC

Der ISO C Sprachstandard verlangt, dass C-Compiler die folgenden drei Pragmas unterstützen. Einige C++-Compiler-Anbieter unterstützen sie in ihren C++-Frontends in unterschiedlichem Maße.

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

wobei arg entweder ON, OFF oder DEFAULT ist.

1) Wenn auf ON gesetzt, informiert es den Compiler, dass das Programm auf die Gleitkomma-Umgebung zugreifen oder diese modifizieren wird. Dies bedeutet, dass Optimierungen, die Flag-Tests und Modusänderungen untergraben könnten (z. B. globale gemeinsame Subausdrucks-Eliminierung, Code-Bewegung und Konstanten-Faltung), verboten sind. Der Standardwert ist implementierungsdefiniert, üblicherweise OFF.
2) Erlaubt das Kontrahieren von Gleitkomma-Ausdrücken, d. h. Optimierungen, die Rundungsfehler und Gleitkomma-Ausnahmen auslassen, die beobachtet würden, wenn der Ausdruck exakt so ausgewertet würde, wie er geschrieben ist. Erlaubt beispielsweise die Implementierung von (x * y) + z mit einer einzigen Fused-Multiply-Add-CPU-Instruktion. Der Standardwert ist implementierungsdefiniert, üblicherweise ON.
3) Informiert den Compiler, dass Multiplikation, Division und 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 von Zwischenüberläufen. Mit anderen Worten, der Programmierer garantiert, dass der Wertebereich der an diese Funktionen übergebenen Werte begrenzt ist. Der Standardwert ist OFF.

Das Verhalten des Programms ist undefiniert, wenn eines der drei oben genannten Pragmas in einem anderen Kontext als außerhalb aller externen Deklarationen oder vor allen expliziten Deklarationen und Anweisungen innerhalb einer zusammengesetzten Anweisung vorkommt.

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

[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 vorkommt, zeigt es an, dass diese nur einmalig übersetzt werden soll, auch wenn sie mehrmals (direkt oder indirekt) in derselben Quelldatei eingebunden wird.

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 bis auf die erste Einbindung des Headers in einer beliebigen Translation Unit von der Kompilierung ausgeschlossen werden. Alle modernen Compiler merken sich die Tatsache, 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 es, da bei #pragma once Dateien anhand ihrer Dateisystem-Identität ausgeschlossen werden, nicht vor dem zweimaligen Einbinden eines Headers schützen, wenn dieser an mehreren Orten in einem Projekt existiert.

[bearbeiten] #pragma pack

Diese Pragma-Familie steuert die maximale Ausrichtung für nachfolgend definierte Klassen- 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) Schiebt den Wert der aktuellen Ausrichtung auf einen internen Stapel.
4) Schiebt den Wert der aktuellen Ausrichtung auf den internen Stapel und setzt dann die aktuelle Ausrichtung auf den Wert arg.
5) Nimmt den obersten Eintrag vom internen Stapel und setzt (stellt) die aktuelle Ausrichtung auf diesen Wert zurück.

#pragma pack kann die Ausrichtung einer Klasse verringern, kann jedoch eine Klasse nicht übermäßig ausrichten.

Siehe spezifische Details für GCC und MSVC.

[bearbeiten] Referenzen

  • C++23 Standard (ISO/IEC 14882:2024)
  • 15.9 Pragma directive [cpp.pragma]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 15.9 Pragma directive [cpp.pragma]
  • C++17 Standard (ISO/IEC 14882:2017)
  • 19.6 Pragma directive [cpp.pragma]
  • C++14 Standard (ISO/IEC 14882:2014)
  • 16.6 Pragma directive [cpp.pragma]
  • C++11 Standard (ISO/IEC 14882:2011)
  • 16.6 Pragma directive [cpp.pragma]
  • C++98 Standard (ISO/IEC 14882:1998)
  • 16.6 Pragma directive [cpp.pragma]

[bearbeiten] Siehe auch

C-Dokumentation für Steuerung des implementierungsdefinierten Verhaltens

[bearbeiten] Externe Links

1.  C++ Pragmas in Visual Studio
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.  Release Notes (einschließlich Pragmas) für HP aCC A.06.25