C에서 #pragma 사용


117

#pragma예제와 함께 C에서 사용하는 것은 무엇입니까 ?


2
#pragma지시문은 전처리 단계에서 살아남습니다. 달리 #include하고 #define.
smwikipedia


@smwikipedia 당신은 pragma가 생존한다는 것을 의미합니까? #pragma once는 전 처리기 지시문이지만 #pragma pack은 컴파일러 지시문입니다
Lewis Kelsey

답변:


66

#pragma 기계 별 또는 운영 체제 별 컴파일러 지시문을위한 것입니다. 즉, 컴파일러에게 작업을 수행하고, 일부 옵션을 설정하고, 조치를 취하고, 일부 기본값을 재정의하도록 지시합니다. 시스템.

자세한 내용은 msdn 을 참조하십시오 .


11
"모든 시스템 및 운영 체제에 적용되거나 적용되지 않을 수 있습니다." -같은 컴퓨터에있는 다른 컴파일러. 그리고 이것은 다른 컴파일러에서 다른 것을 의미 할 수 있습니다.
Steve Jessop

53

#pragma C에서 특정 구현을 수행하는 데 사용됩니다. 즉, 이데올로기 적으로 독단적이기보다는 현재 컨텍스트에 대해 실용적이어야합니다.

내가 정기적으로 사용하는 것은 #pragma pack(1)8 바이트 정렬로 끝나는 구조 배열을 사용하여 임베디드 솔루션에서 메모리 공간을 더 많이 차지하려는 곳입니다.

#dogma아직 안타깝 네요 . 재미 있겟군요 ;)


@ShaneMacLaughlin, pragma(1)속도도 실제로 향상 되지 않습니까? stackoverflow.com/questions/3318410/…
Pacerier

4
@Pacerier는 일반적으로 아닙니다. jalfs 설명에 따라 32 비트 프로세서의 경우 4 바이트 경계 또는 64 비트 프로세서의 경우 8 바이트 경계에 정렬 된 데이터는 일반적으로 단일 작업으로로드되고 저장됩니다. 더 작은 경계에 정렬 된 데이터는로드하거나 저장하는 데 여러 작업이 필요합니다. 이것은 더 느립니다.
SmacL

35

나는 일반적으로 #pragma의 사용을 피하려고 할 것이다. 왜냐하면 그것들은 매우 컴파일러에 의존적이고 이식성이 없기 때문이다. 휴대용 방식으로 사용하려면 모든 pragma를 #if/ #endif쌍 으로 둘러싸 야합니다 . GCC는 pragma의 사용을 권장하지 않으며 실제로 다른 컴파일러와의 호환성을 위해 일부만 지원합니다. GCC에는 다른 컴파일러가 pragma를 사용하는 것과 동일한 작업을 수행하는 다른 방법이 있습니다.

예를 들어, 다음은 MSVC에서 구조가 단단히 패킹되었는지 (즉, 멤버 사이에 패딩이 없는지) 확인하는 방법입니다.

#pragma pack(push, 1)
struct PackedStructure
{
  char a;
  int b;
  short c;
};
#pragma pack(pop)
// sizeof(PackedStructure) == 7

GCC에서 동일한 작업을 수행하는 방법은 다음과 같습니다.

struct PackedStructure __attribute__((__packed__))
{
  char a;
  int b;
  short c;
};
// sizeof(PackedStructure == 7)

GCC 코드는 더 이식성이 있습니다. GCC가 아닌 컴파일러로 컴파일하려면 다음과 같이하면됩니다.

#define __attribute__(x)

MSVC 코드를 이식하려면 각 pragma를 #if/ #endif쌍으로 묶어야 합니다. 예쁘지 않은.


3
그렇다면 MSVC에서 GCC 코드를 컴파일하고 구조를 압축해야한다면 정확히 어떻게해야합니까?
SmacL

2
gcc의 경우 struct __attribute__((__packed__)) PackedStructure
Laurent Debricon

#pragma once는 현실적으로 "컴파일러에 의존하고 이식 할 수 없습니다"가 아닙니다. 모든 주요 플랫폼과 주요하지 않은 많은 플랫폼에서 지원됩니다. en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon

1
C99와 C11에는 모두 (C11) §6.10.6 Pragma 지시문이 포함되어 있으며 ¶1 구현에서 인식되지 않는 모든 pragma는 무시됩니다. C90조차도 섹션 §6.8.6에 있었지만 그렇게 말합니다. (이것은 GCC hack가 인식하지 못하는 pragma를 만났을 때 실행되는 경우 비준수 상태가되게합니다. 예전에는 아주 아주 오래 전에 사용했던 것처럼 참조 #pragma및 GCC 등)
Jonathan Leffler

15

#pragma once헤더 파일의 맨 위에 놓으면 한 번만 포함됩니다. 참고 #pragma onceC99 표준은 아니지만 대부분의 현대적인 컴파일러에 의해 지원.

사용 경비를 포함하는 대신 (예입니다 #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)


7

내가 느끼는 것은 #pragma당신이 코드가 프로그램 카운터가 ISR은 당신이 사용하여 해당 위치에 ISR을 지정할 수 있습니다 후 기록 된 특정 주소에서 읽고 싶은 상황 .say 위치 구체적하려는 경우 지침입니다 #pragma vector=ADC12_VECTOR의해 followd 인터럽트 로틴 이름 및 설명


5

필자의 가장 좋은 조언은 pragma가 정의에 따라 구현에 따라 다르기 때문에 컴파일러의 문서를 보는 것입니다. 예를 들어, 임베디드 프로젝트에서는 다른 섹션에서 코드와 데이터를 찾거나 인터럽트 핸들러를 선언하는 데 사용했습니다. 즉 :

#pragma code BANK1
#pragma data BANK2

#pragma INT3 TimerHandler

3
모든 플랫폼에서 표준화 된 #pragma STDC ... pragma를 제외하고 모든 pragma는 구현에 따라 다릅니다 (C99에 추가).
Jonathan Leffler

4

위의 모든 답변은 좋은 설명 #pragma이지만 작은 예를 추가하고 싶었습니다.

작업을 수행하는 simple OpenMP example데 몇 가지 용도를 보여주는 설명 #pragma을하려고합니다.

OpenMP는 briefly멀티 플랫폼 공유 메모리 병렬 프로그래밍을위한 구현 (다음 우리가 말할 수 있습니다 machine-specific또는 operating-system-specific)

예제로 가자

#include <stdio.h>
#include <omp.h>// compile with: /openmp

int main() {
   #pragma omp parallel num_threads(4)
   {
      int i = omp_get_thread_num();
      printf_s("Hello from thread %d\n", i);
   }
}

출력은

Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3

Note that the order of output can vary on different machines.

이제 무슨 일을 #pragma했는지 말씀 드리겠습니다 ...

4 개의 스레드에서 일부 코드 블록을 실행하도록 OS에 지시합니다.

이것은 many many applications여러분 중 하나 일뿐 입니다.#pragma

외부 샘플 죄송합니다 OpenMP


3

특정 기능을 켜거나 끄는 데 사용할 수있는 전 처리기 지시문입니다.

그것은 두 가지 유형이다 #pragma startup, #pragma exit하고 #pragma warn.

#pragma startup 프로그램 시작시 호출되는 함수를 지정할 수 있습니다.

#pragma exit 프로그램 종료시 호출되는 함수를 지정할 수 있습니다.

#pragma warn 경고를 억제할지 여부를 컴퓨터에 알립니다.

다른 많은 #pragma스타일을 사용하여 컴파일러를 제어 할 수 있습니다.


3

#pragma startup 주 함수 앞에 함수를 호출하고 주 함수 뒤에 다른 함수를 호출하는 데 사용되는 지시문입니다. 예 :

#pragma startup func1
#pragma exit func2

여기서는 func1이전 mainfunc2실행되고 이후에 실행됩니다.

참고 :이 코드는 Turbo-C 컴파일러에서만 작동합니다. GCC에서이 기능을 달성하기 위해 다음 func1func2같이 선언 할 수 있습니다 .

void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();

2

요약 #pragma하면 컴파일러에게 작업을 지시합니다. 사용하는 몇 가지 방법은 다음과 같습니다.

  • #pragma컴파일러 경고를 무시하는 데 사용할 수 있습니다. 예를 들어, 암시 적 함수 선언에 대해 GCC를 종료하려면 다음과 같이 작성할 수 있습니다.

    #pragma GCC diagnostic ignored "-Wimplicit-function-declaration"

    의 이전 버전 libportable은이를 이식 가능하게 합니다.

  • #pragma once, 헤더 파일의 맨 위에 작성되면 해당 헤더 파일이 한 번 포함됩니다. 한 번 지원되는 pragma를 libportable 확인 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.