Spec-Zone.ru › C++

Управление поведением, определяемым реализацией

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

Синтаксис

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

Пояснение

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

Нестандартные pragma

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

#pragma STDC

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

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

где arg — это ON, OFF или DEFAULT.

1) Если установлено значение ON, сообщает компилятору, что программа будет обращаться к среде вычислений с плавающей точкой или изменять её. Это означает, что оптимизации, которые могут помешать проверке флагов и изменению режимов (например, глобальное устранение общих подвыражений, перемещение кода и свёртка констант), запрещены. Значение по умолчанию определяется реализацией, обычно это OFF.
2) Разрешает объединение выражений с плавающей точкой, то есть оптимизации, исключающие ошибки округления и исключения с плавающей точкой, которые возникли бы при вычислении выражения точно в записанном виде. Например, это позволяет реализовать (x * y) + z одной инструкцией ЦП fused multiply-add. Значение по умолчанию определяется реализацией, обычно это ON.
3) Сообщает компилятору, что для умножения, деления и вычисления абсолютного значения комплексных чисел могут использоваться упрощённые математические формулы (x+iy)×(u+iv) = (xu-yv)+i(yu+xv), (x+iy)/(u+iv) = [(xu+yv)+i(yu-xv)]/(u2+v2) и |x+iy| = √x2+y2, несмотря на возможность промежуточного переполнения. Иными словами, программист гарантирует, что диапазон значений, передаваемых этим функциям, ограничен. Значение по умолчанию — OFF.

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

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

#pragma once

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

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

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

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

С #pragma once тот же заголовок выглядит так:

#pragma once
// contents of the header

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

#pragma pack

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

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

где 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. Pragma в C++ в Visual Studio
2. Pragma, поддерживаемые GCC
3. Описания отдельных pragma и стандартные pragma в IBM AIX XL C 16.1
4. Приложение B. Pragma в руководстве пользователя Sun Studio 11 C++
5. Pragma компилятора Intel C++
6. Примечания к выпуску (включая pragma) для HP aCC A.06.25

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/preprocessor/impl

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API