Namespaces
Variants

Implementation defined behavior control

From cppreference.net

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

Содержание

Синтаксис

#pragma pragma_params (1)
_Pragma ( string-literal ) (2) (начиная с C99)
1) Весёт себя определённым в реализации образом (если только pragma_params не является одной из стандартных прагм, приведённых ниже).
2) Удаляет префикс кодировки (если есть), внешние кавычки и начальные/конечные пробелы из string-literal , заменяет каждую последовательность \" на " и каждую последовательность \\ на \ , затем токенизирует результат (как в фазе трансляции 3 ), и затем использует результат как если бы это был ввод для #pragma в (1) .

Объяснение

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

Стандартные прагмы

Следующие три директивы pragma определены стандартом языка:

#pragma STDC FENV_ACCESS аргумент (1) (начиная с C99)
#pragma STDC FP_CONTRACT аргумент (2) (начиная с C99)
#pragma STDC CX_LIMITED_RANGE аргумент (3) (начиная с C99)

где 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 в gcc.

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

#pragma once

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

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

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

Чтобы все включения заголовочного файла, кроме первого, в любой единице трансляции исключались из компиляции. Все современные компиляторы запоминают факт использования стражей включения в заголовочном файле и не выполняют повторный разбор файла при повторном его обнаружении, пока страж остается определенным (см., например, 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 .

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2024):
  • 6.10.6 Директива pragma (стр.: TBD)
  • 6.10.9 Оператор pragma (стр.: TBD)
  • Стандарт C17 (ISO/IEC 9899:2018):
  • 6.10.6 Директива Pragma (стр. 127)
  • 6.10.9 Оператор Pragma (стр. 129)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 6.10.6 Директива Pragma (стр. 174)
  • 6.10.9 Оператор Pragma (стр. 178)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 6.10.6 Директива pragma (стр. 159)
  • 6.10.9 Оператор pragma (стр. 161-162)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 3.8.6 Директива 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