본문 바로가기
개발/C/C++

[C/C++]유용한 #pragma directive

by esstory 2007.09.05

※ 주의 : 아래에서 기술하는 내용은 Visual C++ 컴파일러에서만 확인된 내용입니다.


지난번 #define 팁 에 이어 이번에는 필수는 아니지만 사용할 경우 아주 편리한 #pragma 지시자를 간단하게 소개하려고 합니다.


1. 헤더 파일을 한번만 읽어 들이기


아마도 이 경우가 #pragma를 가장 널리 사용하게 된 이유 중에 하나라고 생각되는데요

저도 언제나 헤더 파일을 새로 코딩 할 때 이 한 줄을 먼저 적게 됩니다. (아주 짧고 멋집니다)

#pragma once

#pragma once 가 없을 당시에는 아래와 같이 헤더 파일 내용을 #ifndef ~  #endif 문장을 사용해서 복잡하게 써주어야 했습니다. (요 복잡한 게 한 줄로 줄었으니 사용하지 않을 수 없죠^^)

#ifndef _MY_HEADER_FILE_H_

#define _MY_HEADER_FILE_H_

// 실제헤더파일내용

 

#endif

하지만 이러한 방식은 헤더 파일마다 새로운 이름의 #define 문을 작성해야 했고 실수로 #endif 를 빼먹거나, #ifndef 과 짝을 잘못 이룬 경우 코딩과 상관없이 재앙을 불러오기 일쑤였습니다.

Visual Studio .NET 2003버전부터였던 것으로 기억되는데 프로젝트 위저드가 자동으로 만들어내는 헤더 파일에 #pragma once 가 들어 있어 그때부터 제가 만드는 헤더 파일도 이 방법을 애용하게 되었습니다.

 

2. Structure Alignment 조정하기


클라이언트 프로그램을 하다 보면 UNIX 나 기타 서버와 소켓연결을 통해 데이터를 주고 받는 경우가 많습니다. 서버와 통신을 하다 보면, 보통 UNIX 로부터 전송되는 구조체와 클라이언트 프로그램의 구조체의 Alignment를 맞춰주어야 하는 경우가 생깁니다.

#pragma 를 사용해서 구조체 Align 을 조정할 수 있다는 것을 몰랐던 시절에는 하는 수 없이 전체 프로젝트의 Align 속성을 ‘1’ 바이트로 변경하곤 했습니다.

사용자 삽입 이미지

이렇게 할 경우

-       Structure Alignment 를 기본인 8바이트로 사용할 경우보다 약간의 메모리 접근 성능이 저하되고

-       3’rd Party Library 와 구조체를 주고 받을 때 양쪽이 Alignment 가 틀려 고생할 가능성이 생기고

-       프로젝트를 신규 생성할 때마다 Alignment 값을 변경하지 않으면 이 역시 코딩과는 상관없이 서버로부터 받은 데이터가 몽땅 깨지는 현상을 만나는 문제가 있었습니다.

그래서 가급적이면 꼭 필요한 구조체에 대해서만(이 경우 서버와 통신하는 구조체) Structure Alignment 를 조정하는 것이 좋습니다.

#pragma pack 을 사용하면 특정 구조체만 간단하게 Alignment 속성을 바꿀 수 있습니다.

#pragma pack(push, 1)

struct ABC

{

           int BaseOption1;

           int BaseOption2;

           int BaseOption3;

           char szText[100];

           BYTE szAddress[100];

};

#pragma pack(pop)

#pragma pack 의 괄호 안에 들어가는 숫자 ‘1’ 1바이트로 Alignment 를 하라는 지시이고, #pragma pack(pop)은 이전 상태(디폴트가 8 바이트 Alignment 이면 8 바이트)로 돌아가라는 지시어입니다.

알고 보면 너무 간단한데 몇 년 동안 이 방법을 몰라 고생했더랬습니다.

 

3. 귀찮고 처치 곤란한 경고 메시지 없애기


좋은 프로그램을 작성하는 개발자라면 늘 Warning Level 을 최고로 올려 빌드 하실 텐데요

이 경우 의미 없는 경고도 어쩔 수 없이 많이 만나게 됩니다.

특히 .NET 2005 에서는 버그인지 모르겠지만, 주석문에 들어 있는 한글을 만나면 희한한 경고를 만나게 되는 경우가 많습니다.

warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss

가능한 모든 경고는 없애야겠지만, 어쩔 수 없이 무시하고 넘겨야 하는 경고들도 있는데 이런 경고들은 다음 번 빌드부터는 보지 않도록 아래와 같이 지정할 수 있습니다.

#pragma warning (disable:4819)

위 내용은 4819 오류 경고 표시를 하지 말라는 뜻으로 쓰입니다. 이 경우도 push pop 을 사용해서 특정 소스에서만 경고가 안 나오게 설정할 수도 있습니다.

 

4. 라이브러리 링크하기

사용자 삽입 이미지

일반적으로 라이브러리를 링크하는 방법은 프로젝트 Linker 옵션에서 사용할 프로젝트 라이브러리를 지정해 주는 방식을 많이 사용합니다.

#pragma 를 사용하면, 프로그램 소스에서 직접 다른 라이브러리를 링크할 수 있습니다.

#pragma comment( lib, "../TEST_DLL/release/Testdll.Lib" )

이 방식은 프로젝트 속성창 > 링크옵션 > Testdll.lib 를 추가하는 것과 동일한 방식으로 라이브러리를 링크합니다.

프로젝트 속성을 통해 링크를 지정하는 방식과, #pragma 를 통해 링크를 지정하는 것 중 저희는 후자를 선호합니다.

후자와 같이 프로그램 소스에 링크 정보가 있을 경우 특정 모듈에 대한 종속정보를 단순히 소스 검색을 통해서 확인할 수 있고 프로젝트가 변경, 확장, 제거 될 때 마다 매번 프로젝트 속성을 재차 확인해야 하는 번거로움도 없어 자주 사용하게 되더군요

 

그외에도 MSDN에서 #pragma 를 찾아 보면 상당히 많은 지시자가 있는데 혹 공유할만한 내용 있으시면 많은 지적 바랍니다.

 

Daum 블로거뉴스에서 이 포스트를 추천해주세요. [추천]


댓글9

  • BlogIcon 키눅스 2007.09.05 15:51

    다른 것들은 알고 있었는데 #pragma once 는 처음 알았네요.
    항상 헤더파일 코딩시 #ifndef 로 시작하는게 버릇이었는데... 이제 습관을 바꿔야 겠네요.
    좋은 정보 감사합니다.
    답글

    • BlogIcon esstory 2007.09.05 16:06 신고

      저도 몇년전 컴파일러를 바꾸면서 알게 되었습니다. Visual C++ 6.0 에서도 작동하는지는 아직 모르겠습니다. 지원된다면 #ifndef 보다는 많이 편하실거예요. ^^;

  • findfun 2009.05.27 11:48

    오호 감사합니다.
    답글

  • 삼류개발자 2009.12.10 19:35

    한 1년전쯤인가? 우리 회사에 오래되고 매우 무거운 프로젝트 (480만 라인 정도되는 대형 프로젝트..)가..
    VC++ 6 으로 개발된건데.. 기능 추가하게 될 일이 생겨서 새로운 클래스 헤더에 #pragma once
    적용해 보았는데 잘 되네요..
    답글

  • starred49 2012.02.01 11:16

    좋은정보 얻어갑니다:)

    답글

  • 학생 2014.01.02 10:41

    이 글도 퍼갑니다, 좋은 정보가 많네요. 감사합니다.
    답글