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

Поведение, определяемое реализацией, контролируется с помощью #pragma директивы.

Содержание

Синтаксис

#pragma pragma-params (1)
_Pragma( string-literal ) (2) (начиная с C++11)
1) Поведение определяется реализацией.
2) Удаляет префикс L (если присутствует), внешние кавычки и ведущие/завершающие пробелы из string-literal , заменяет каждую \ " на " и каждую \\ на \ , затем токенизирует результат (как в фазе трансляции 3 ), и затем использует результат, как если бы это был ввод для #pragma в (1) .

Объяснение

Директива Pragma управляет поведением компилятора, специфичным для реализации, таким как отключение предупреждений компилятора или изменение требований к выравниванию. Любая нераспознанная прагма игнорируется.

Нестандартные прагмы

Стандарт языка ISO C++ не требует от компиляторов поддержки каких-либо прагм. Однако несколько нестандартных прагм поддерживаются многими реализациями:

#pragma STDC

Стандарт языка ISO C требует, чтобы компиляторы C поддерживали следующие три прагмы, и некоторые производители компиляторов C++ поддерживают их в разной степени в своих фронтендах для C++:

#pragma STDC FENV_ACCESS аргумент (1)
#pragma STDC FP_CONTRACT аргумент (2)
#pragma STDC CX_LIMITED_RANGE аргумент (3)

где arg может быть ON , OFF или DEFAULT .

1) Если установлено в ON , информирует компилятор, что программа будет обращаться или изменять floating-point environment , что означает, что оптимизации, которые могут нарушать проверки флагов и изменения режимов (например, глобальное устранение общих подвыражений, перемещение кода и свертка констант), запрещены. Значение по умолчанию определяется реализацией, обычно OFF .
2) Позволяет объединение выражений с плавающей точкой, то есть оптимизации, которые исключают ошибки округления и исключения с плавающей точкой, которые наблюдались бы, если бы выражение вычислялось точно так, как записано. Например, позволяет реализацию ( x * y ) + z с помощью одной инструкции FMA (умножение-сложение) процессора. Значение по умолчанию определяется реализацией, обычно ON .
3) Сообщает компилятору, что умножение, деление и вычисление абсолютного значения комплексных чисел могут использовать упрощённые математические формулы (x+iy)×(u+iv) = (xu-yv)+i(yu+xv) , (x+iy)/(u+iv) = [(xu+yv)+i(yu-xv)]/(u 2
+v 2
)
, и |x+iy| = x 2
+y 2
, несмотря на возможность промежуточного переполнения. Другими словами, программист гарантирует, что диапазон значений, передаваемых этим функциям, ограничен. Значение по умолчанию — OFF .

Поведение программы не определено, если любая из трех приведенных выше прагм появляется в любом контексте, кроме как вне всех внешних объявлений или предшествует всем явным объявлениям и операторам внутри составного оператора.

Примечание: компиляторы, не поддерживающие эти прагмы, могут предоставлять эквивалентные опции времени компиляции, такие как -fcx-limited-range и -ffp-contract .

#pragma once

#pragma once — это нестандартная прагма, поддерживаемая подавляющим большинством современных компиляторов . Если она появляется в заголовочном файле, это означает, что он должен быть обработан только один раз, даже если он включен (напрямую или косвенно) несколько раз в том же исходном файле.

Стандартный подход для предотвращения многократного включения одного и того же заголовка заключается в использовании include guards :

#ifndef LIBRARY_FILENAME_H
#define LIBRARY_FILENAME_H
// содержимое заголовочного файла
#endif /* LIBRARY_FILENAME_H */

Чтобы все включения заголовочного файла, кроме первого, в любой единице трансляции исключались из компиляции. Все современные компиляторы запоминают факт использования include guard в заголовочном файле и не выполняют повторный разбор файла при повторном его обнаружении, пока guard остается определенным (см., например, gcc ).

С помощью #pragma once тот же заголовок появляется как

#pragma once
// содержимое заголовочного файла

В отличие от стражей заголовков, эта директива делает невозможным ошибочное использование одного и того же имени макроса в нескольких файлах. С другой стороны, поскольку с #pragma once файлы исключаются на основе их идентификатора на уровне файловой системы, это не может защитить от двукратного включения заголовка, если он существует в нескольких местах проекта.

#pragma pack

Это семейство прагм управляет максимальным выравниванием для последующих членов классов и объединений.

#pragma pack( arg ) (1)
#pragma pack() (2)
#pragma pack(push) (3)
#pragma pack(push, arg ) (4)
#pragma pack(pop) (5)
**Примечание:** Весь код внутри тегов ` ` и `
` оставлен без изменений, так как содержит C++ специфические термины и директивы препроцессора, которые не подлежат переводу. HTML структура и атрибуты также полностью сохранены.

где arg является малой степенью двойки и задает новое выравнивание в байтах.

1) Устанавливает текущее выравнивание в значение arg .
2) Устанавливает текущее выравнивание на значение по умолчанию (заданное параметром командной строки).
3) Помещает значение текущего выравнивания во внутренний стек.
4) Помещает значение текущего выравнивания во внутренний стек, а затем устанавливает текущее выравнивание в значение arg .
5) Извлекает верхнюю запись из внутреннего стека и затем устанавливает (восстанавливает) текущее выравнивание на это значение.

#pragma pack может уменьшить выравнивание класса, однако не может сделать класс перевыровненным.

См. также конкретные детали для GCC и MSVC .

Ссылки

  • Стандарт C++23 (ISO/IEC 14882:2024):
  • 15.9 Директива pragma [cpp.pragma]
  • Стандарт C++20 (ISO/IEC 14882:2020):
  • 15.9 Директива pragma [cpp.pragma]
  • Стандарт C++17 (ISO/IEC 14882:2017):
  • 19.6 Директива pragma [cpp.pragma]
  • Стандарт C++14 (ISO/IEC 14882:2014):
  • 16.6 Директива Pragma [cpp.pragma]
  • Стандарт C++11 (ISO/IEC 14882:2011):
  • 16.6 Директива pragma [cpp.pragma]
  • Стандарт C++98 (ISO/IEC 14882:1998):
  • 16.6 Директива Pragma [cpp.pragma]

Смотрите также

Документация C для Управление поведением, определяемым реализацией

Внешние ссылки

1. Прагмы C++ в Visual Studio
2. Прагмы поддерживаемые GCC
3. Описания отдельных прагм и Стандартные прагмы в IBM AIX XL C 16.1
4. Приложение Б. Прагмы в руководстве пользователя Sun Studio 11 C++
5. Прагмы компилятора Intel C++
6. Узлы выпуска (включая прагмы) для HP aCC A.06.25