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 에서와 같이), 그 결과를 (1) 에서 #pragma 의 입력인 것처럼 사용합니다.

설명

pragma 지시문은 컴파일러 경고 비활성화나 정렬 요구사항 변경과 같은 컴파일러의 구현별 동작을 제어합니다. 인식되지 않는 모든 pragma는 무시됩니다.

표준 프라그마

다음 세 가지 프라그마는 언어 표준에 의해 정의됩니다:

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

여기서 arg ON 또는 OFF 또는 DEFAULT 입니다.

1) ON 으로 설정되면, 프로그램이 floating-point environment 에 접근하거나 수정할 것임을 컴파일러에 알립니다. 이는 플래그 테스트와 모드 변경을 무효화할 수 있는 최적화(예: 전역 공통 부분 표현식 제거, 코드 이동, 상수 폴딩)가 금지됨을 의미합니다. 기본값은 구현에 따라 정의되며, 일반적으로 OFF 입니다.
2) 부동 소수점 표현식의 계약 을 허용합니다. 즉, 표현식이 작성된 그대로 정확히 평가되었을 때 관찰되었을 반올림 오류 및 부동 소수점 예외를 생략하는 최적화를 허용합니다. 예를 들어, ( x * y ) + z 를 단일 FMA(Fused Multiply-Add) CPU 명령어로 구현하는 것을 허용합니다. 기본값은 구현에 따라 정의되며, 일반적으로 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 입니다.

참고: 이러한 프라그마를 지원하지 않는 컴파일러는 gcc의 -fcx-limited-range -ffp-contract 와 같은 동등한 컴파일 타임 옵션을 제공할 수 있습니다.

비표준 프라그마

#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)

여기서 arg 는 2의 작은 거듭제곱이며 바이트 단위의 새로운 정렬을 지정합니다.

1) 현재 정렬을 값 arg 로 설정합니다.
2) 현재 정렬을 기본값(명령줄 옵션으로 지정된)으로 설정합니다.
3) 현재 정렬 값을 내부 스택에 푸시합니다.
4) 내부 스택에 현재 정렬 값을 푸시한 다음 현재 정렬을 값 arg 으로 설정합니다.
5) 내부 스택에서 최상위 항목을 꺼낸 다음 현재 정렬을 해당 값으로 설정(복원)합니다.

#pragma pack 는 구조체의 정렬을 감소시킬 수 있지만, 구조체를 과도하게 정렬되게 만들 수는 없습니다.

자세한 내용은 GCC MSVC 에 대한 구체적인 설명을 참조하십시오.

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.10.6 Pragma directive (p: TBD)
  • 6.10.9 Pragma operator (p: TBD)
  • C17 표준 (ISO/IEC 9899:2018):
  • 6.10.6 Pragma directive (p: 127)
  • 6.10.9 Pragma operator (p: 129)
  • C11 표준 (ISO/IEC 9899:2011):
  • 6.10.6 Pragma 지시문 (p: 174)
  • 6.10.9 Pragma 연산자 (p: 178)
  • C99 표준 (ISO/IEC 9899:1999):
  • 6.10.6 Pragma directive (p: 159)
  • 6.10.9 Pragma operator (p: 161-162)
  • C89/C90 표준 (ISO/IEC 9899:1990):
  • 3.8.6 Pragma directive

참고 항목

C++ documentation for Implementation defined behavior control

외부 링크

1. Visual Studio의 C++ 프라그마
2. GCC에서 지원하는 프라그마
3. 개별 프라그마 설명 표준 프라그마 (IBM AIX XL C 16.1)
4. 부록 B. 프라그마 (Sun Studio 11 C++ 사용자 가이드)
5. Intel C++ 컴파일러 프라그마
6. HP aCC 컴파일러 프라그마