Пространства имён
Варианты
Действия

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

Материал из cppreference.com
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений(до C++17*)
Спецификатор noexcept(C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype(C++11)
auto(C++11)
alignas(C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr(C++11)
Определяемые пользователем(C++11)
Утилиты
Атрибуты(C++11)
Types
Объявление typedef
Объявление псевдонима типа(C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
Специальные функции-элементы
Шаблоны
Разное
 
 

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

Содержание

[править]Синтаксис

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

[править]Объяснение

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

[править]Нестандартные прагмы

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

[править]#pragma STDC

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

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

где аргумент равно ON, OFF или DEFAULT.

1) Если установлено значение ON, это информирует компилятор о том, что программа будет обращаться или изменять среду с плавающей запятой, что означает, что оптимизации, которые могут нарушить проверку флагов и изменения режима (например, глобальное устранение общих подвыражений, перемещение кода и сворачивание констант) запрещены. Значение по умолчанию определяется реализацией, обычно OFF.
2) Позволяет сжимать выражения с плавающей запятой, то есть позволяет оптимизацию, которая пропускает ошибки округления и исключения с плавающей запятой, которые наблюдались бы, если бы выражение было вычислено точно так, как написано. Например, позволяет реализовать (x*y)+ z одной объединенной инструкцией процессора умножения и сложения. Значение по умолчанию определяется реализацией, обычно 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.

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

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

[править]#pragma once

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

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

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

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

С #pragma once тот же заголовок отображается как

#pragma once// содержимое заголовка

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

[править]#pragma pack

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

#pragma pack(аргумент) (1)
#pragma pack() (2)
#pragma pack(push) (3)
#pragma pack(push, аргумент) (4)
#pragma pack(pop) (5)

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

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

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

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

[править]Ссылки

  • C++23 стандарт (ISO/IEC 14882:2023):
  • 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 2019
2. Прагмы, принятые GCC
3. Индивидуальные описания прагм и Стандартные прагмы в IBM AIX XL C 16.1}}
4. Приложение B. Прагмы в Руководстве Пользователя Sun Studio 11 C++
5. Прагмы компилятора Intel C++
6. Выпущенные узлы (включая прагмы) для HP aCC A.06.25
close