Namespaces
Variants

Implementation defined behavior control

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Le comportement défini par l'implémentation est contrôlé par la directive #pragma .

Table des matières

Syntaxe

#pragma pragma-params (1)
_Pragma( string-literal ) (2) (depuis C++11)
1) Se comporte de manière définie par l'implémentation.
2) Supprime le préfixe L (le cas échéant), les guillemets externes et les espaces blancs de début/fin de string-literal , remplace chaque \ " par " et chaque \\ par \ , puis tokenise le résultat (comme dans la phase de traduction 3 ), et utilise ensuite le résultat comme s'il s'agissait de l'entrée de #pragma dans (1) .

Explication

La directive pragma contrôle le comportement spécifique à l'implémentation du compilateur, comme la désactivation des avertissements du compilateur ou la modification des exigences d'alignement. Tout pragma non reconnu est ignoré.

Pragmas non standard

La norme du langage ISO C++ n'exige pas que les compilateurs prennent en charge des pragmas. Cependant, plusieurs pragmas non standard sont pris en charge par de multiples implémentations :

#pragma STDC

La norme ISO du langage C exige que les compilateurs C prennent en charge les trois pragmas suivants, et certains fournisseurs de compilateurs C++ les supportent, à divers degrés, dans leurs frontends C++ :

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

arg est soit ON , OFF , ou DEFAULT .

1) Si défini sur ON , informe le compilateur que le programme accédera ou modifiera l' environnement en virgule flottante , ce qui signifie que les optimisations qui pourraient compromettre les tests de drapeaux et les changements de mode (par exemple, l'élimination des sous-expressions communes globales, le déplacement de code et le pliage constant) sont interdites. La valeur par défaut est définie par l'implémentation, généralement OFF .
2) Permet la contraction d'expressions à virgule flottante, c'est-à-dire des optimisations qui omettent les erreurs d'arrondi et les exceptions de virgule flottante qui seraient observées si l'expression était évaluée exactement comme écrite. Par exemple, permet l'implémentation de ( x * y ) + z avec une seule instruction CPU de type fused multiply-add. La valeur par défaut est définie par l'implémentation, généralement ON .
3) Informe le compilateur que la multiplication, la division et la valeur absolue des nombres complexes peuvent utiliser des formules mathématiques simplifiées (x+iy)×(u+iv) = (xu-yv)+i(yu+xv) , (x+iy)/(u+iv) = [(xu+yv)+i(yu-xv)]/(u 2
+v 2
)
, et |x+iy| = x 2
+y 2
, malgré la possibilité de dépassement intermédiaire. En d'autres termes, le programmeur garantit que la plage des valeurs qui seront passées à ces fonctions est limitée. La valeur par défaut est OFF .

Le comportement du programme est indéfini si l'une des trois pragmas ci-dessus apparaît dans un contexte autre qu'en dehors de toutes les déclarations externes ou précédant toutes les déclarations explicites et les instructions à l'intérieur d'une instruction composée.

Remarque : les compilateurs qui ne prennent pas en charge ces pragmas peuvent fournir des options de compilation équivalentes, telles que -fcx-limited-range et -ffp-contract de gcc.

#pragma once

#pragma once est un pragma non standard qui est pris en charge par la grande majorité des compilateurs modernes . S'il apparaît dans un fichier d'en-tête, cela indique qu'il ne doit être analysé qu'une seule fois, même s'il est inclus (directement ou indirectement) plusieurs fois dans le même fichier source.

L'approche standard pour empêcher l'inclusion multiple du même en-tête consiste à utiliser les gardes d'inclusion :

#ifndef LIBRARY_FILENAME_H
#define LIBRARY_FILENAME_H
// contenu de l'en-tête
#endif /* LIBRARY_FILENAME_H */

Ainsi, toutes les inclusions du fichier d'en-tête dans une unité de traduction, sauf la première, sont exclues de la compilation. Tous les compilateurs modernes enregistrent le fait qu'un fichier d'en-tête utilise une garde d'inclusion et ne réanalysent pas le fichier s'il est rencontré à nouveau, tant que la garde est toujours définie (voir par exemple gcc ).

Avec #pragma once , le même en-tête apparaît comme

#pragma once
// contenu de l'en-tête

Contrairement aux gardes d'en-tête, ce pragma rend impossible l'utilisation erronée du même nom de macro dans plusieurs fichiers. En revanche, puisque avec #pragma once les fichiers sont exclus en fonction de leur identité au niveau du système de fichiers, cela ne peut pas protéger contre l'inclusion deux fois d'un en-tête s'il existe à plusieurs emplacements dans un projet.

#pragma pack

Cette famille de pragmas contrôle l'alignement maximum pour les membres de classe et d'union définis ultérieurement.

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

arg est une petite puissance de deux et spécifie le nouvel alignement en octets.

1) Définit l'alignement actuel à la valeur arg .
2) Définit l'alignement actuel sur la valeur par défaut (spécifiée par une option de ligne de commande).
3) Pousse la valeur de l'alignement actuel sur une pile interne.
4) Empile la valeur de l'alignement actuel sur la pile interne puis définit l'alignement actuel à la valeur arg .
5) Dépile l'entrée supérieure de la pile interne puis définit (restaure) l'alignement actuel à cette valeur.

#pragma pack peut diminuer l'alignement d'une classe, cependant, il ne peut pas rendre une classe sur-alignée.

Voir également les détails spécifiques pour GCC et MSVC .

Références

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

Voir aussi

Documentation C pour Contrôle du comportement défini par l'implémentation

Liens externes

1. Pragmas C++ dans Visual Studio
2. Pragmas acceptés par GCC
3. Descriptions individuelles des pragmas et Pragmas standard dans IBM AIX XL C 16.1
4. Annexe B. Pragmas dans le Guide de l'utilisateur Sun Studio 11 C++
5. Pragmas du compilateur Intel C++
6. Nœuds de version (inclut les pragmas) pour HP aCC A.06.25