1. 그 기능은 컴파일러의 상태를 설정하거나 컴파일러에게 특정 작업을 완료하도록 지시하는 것입니다. #pragma 지시문은 각 컴파일러가 C 및 C++ 언어와의 완전한 호환성을 유지하면서 호스트 또는 운영 체제별 기능을 제공하는 방법을 제공합니다. 정의에 따르면 pragma는 특정 컴퓨터 또는 운영 체제이며 각 컴파일러마다 다릅니다.
2. 일반적으로 사용되는 pragma 명령어에 대한 자세한 설명입니다.
1.#pragma 한 번. 파일은 한 번만 포함되도록 보장되며, #ifndef는 매크로를 기반으로 합니다.
2. #pragma 경고. 컴파일러 경고 메시지의 동작을 선택적으로 수정할 수 있습니다. 사용법은 다음과 같습니다:
#pragma warning(disable:4507 34; 한 번:4385; 오류:164)는 다음과 같습니다:
#pragma warning(disable:4507 34) // 경고 메시지 4507 및 34를 표시하지 않음
#pragma warning(once:4385) // 경고 메시지 번호 4385는 한 번만 보고됩니다.
#pragma warning(error:164 ) // Put 경고 메시지 164번은 오류로 처리
#pragma warning(default:176) //176번 컴파일러의 경고 동작을 기본 상태로 재설정
동시에 이 pragma 경고는 다음 형식도 지원합니다. 여기서 n은 경고 수준(1---4)을 나타냅니다.
#pragma warning(push) // 모든 경고 상태를 저장합니다. 경고 정보
#pragma warning(push,n) // 모든 경고 메시지의 기존 경고 상태를 저장하고 전역 경보 수준을 n으로 설정합니다.
#pragma warning(pop) // Congquemu Widow thorn萐ush를 복원하고 팝 사이에 이루어진 모든 변경 사항은 취소됩니다.
예:
#pragma warning(push)
#pragma warning(disable:4705)
#pragma warning(disable:4706)
#pragma warning(disable:4707)
#pragma warning(pop) < /p>
이 단락에서는 코드 다음의 모든 경고 메시지(4705, 4706 및 4707 포함)가 복원됩니다.
3. #pragma hdrstop. 미리 컴파일된 헤더 파일이 여기서 끝나고 후속 헤더 파일은 미리 컴파일되지 않음을 나타냅니다. BCB는 링크 속도를 높이기 위해 헤더 파일을 미리 컴파일할 수 있지만 모든 헤더 파일을 미리 컴파일하면 너무 많은 디스크 공간을 차지할 수 있으므로 이 옵션을 사용하여 일부 헤더 파일을 제외할 수 있습니다.
4. #pragma 메시지. 프로그램을 종료하지 않고 지정된 텍스트 메시지를 표준 출력 장치에 출력합니다. 사용법은 다음과 같습니다:
#pragma message("메시지 텍스트"). 컴파일러가 이 명령어를 발견하면 컴파일 출력 창에 "메시지 텍스트"를 인쇄합니다.
5.#pragma data_seg. 일반적으로 DLL에서 사용되며, 프로그램 내 초기화 변수가 위치하는 데이터 세그먼트를 obj 파일에 설정할 수 있습니다.
매개변수가 지정되지 않은 경우 초기화 변수는 다음 사용법에 따라 기본 데이터 세그먼트.data에 배치됩니다.
#pragma data_seg("Shared") // 데이터 세그먼트 "Shared"가 정의됩니다. , 그 중 a와 b가 있습니다.
int a = 0; // "Shared" 데이터 세그먼트에 저장됩니다.
int b; .bss" 초기화가 없기 때문에
#pragma data_seg() // 데이터 세그먼트 "공유"의 끝을 나타냅니다. 이 코드 줄은 선택 사항입니다.
중요한 것은 특별히 변수를 초기화하지 않으면 컴파일됩니다. 컴파일러는 공유 대신 초기화되지 않은 일반 데이터 세그먼트에 변수를 넣습니다. 위에서 보듯이 변수 b는 실제로 초기화되지 않은 데이터 세그먼트.bss에 배치됩니다.
#pragma data_seg("Shared")
int j = 0; // "Shared" 데이터 세그먼트에 저장됨
#pragma data_seg(push, stack1, "Shared2") //데이터 세그먼트 Shared2를 정의하고 레코드에 별칭 stack1을 지정한 다음 내부 컴파일러 스택에 넣습니다.
int l = 0 // 데이터 세그먼트에 저장합니다. Shared2" 중간
#pragma data_seg(pop, stack1) // stack1이 팝될 때까지 내부 컴파일러 스택에서 레코드를 팝합니다. stack1이 없으면 아무 작업도 수행되지 않습니다.
int m = 0; // "Shared" 데이터 세그먼트에 저장됩니다. 위에서 언급한 pop 세그먼트가 없으면 변수는 "Shared2" 데이터 세그먼트에 저장됩니다.
6.#pragma code_seg. 프로그램의 기능이 obj 파일에 위치하는 코드 세그먼트를 설정할 수 있습니다. 매개변수가 지정되지 않으면 함수는 다음 사용법과 함께 기본 코드 세그먼트.text에 배치됩니다.
void func1() { // 기본값은 코드 세그먼트.text에 저장됩니다.
< p>}#pragma code_seg(".my_data1")
void func2() { // 코드 세그먼트 .my_data1에 저장됨
}
< p>#pragma code_seg(push, r1, ".my_data2")void func3() { // 코드 세그먼트 .my_data2에 저장됨
}
#pragma code_seg(pop, r1)
void func4() { // 코드 세그먼트.my_data1에 저장됨
}
7.#pragma pack . 컴파일러의 바이트 정렬을 변경하는 데 사용됩니다.
일반적인 사용법은 다음과 같습니다.
#pragma pack(n) //컴파일러의 바이트 정렬을 n으로 설정합니다. n의 값은 일반적으로 1, 2, 4, 8, 16이고 기본값은 일반적으로 8입니다. /p>
#pragma pack(show) //현재 바이트 정렬을 경고 메시지로 출력
#pragma pack(push) //현재 바이트 메서드를 내부 컴파일러 스택에 정렬
p>
#pragma pack(push,4) //바이트 정렬 4를 내부 컴파일러 스택에 넣고 현재 메모리 정렬을 4로 설정합니다.
#pragma pack(pop) //팝 내부 컴파일러 스택의 상단에 기록하고 이를 현재 메모리 정렬로 사용합니다.
#pragma pack(pop,4) //내부 컴파일러 스택의 상단에 레코드를 팝하고 4를 다음과 같이 사용합니다. 현재 메모리 정렬
#pragma pack(pop,r1) //r1은 사용자 정의 식별자이고 현재 메모리 정렬로 4를 사용합니다. 레코드는 r1이 나타날 때까지 팝업되며 값은 r1은 현재 메모리 정렬로 사용됩니다. r1이 없으면 어떤 작업도 수행되지 않습니다.
8.#pragma 주석. 주석 레코드를 개체 파일이나 실행 파일에 넣습니다.
형식은 #pragma comment( comment-type [,"commentstring"] )입니다. 그 중 comment-type은 주석의 종류를 지정하는 미리 정의된 식별자로 컴파일러, exestr, lib, 링커, 사용자 중 하나이어야 합니다.
컴파일러: 컴파일러 버전이나 이름을 개체 파일에 넣습니다. 이 옵션은 링커에서 무시됩니다.
exestr: 향후 버전에서는 취소될 예정입니다.
lib: 라이브러리 검색 기록을 개체 파일에 배치합니다. 이 유형은 commentstring으로 지정된 라이브러리 유형과 일치해야 합니다(링커가 검색할 lib의 이름과 경로를 지정합니다). 개체 파일에서 라이브러리 이름은 기본 검색 레코드를 따릅니다. 링커는 명령줄에 명령을 입력하는 것과 마찬가지로 이 라이브러리를 검색합니다. 하나의 소스 파일에 여러 개의 라이브러리 검색 기록을 설정할 수 있으며, obj 파일에 나타나는 순서는 소스 파일에 나타나는 순서와 동일합니다.
기본 라이브러리와 추가 라이브러리의 순서를 구분해야 하는 경우 /Zl 컴파일 스위치를 사용하여 기본 라이브러리가 개체 모듈에 배치되지 않도록 하세요.
링커: 명령줄에 입력하거나 개발 환경에서 설정할 필요가 없도록 연결 옵션을 지정합니다. 다음 링커 옵션만 링커에 전달할 수 있습니다:
/DEFAULTLIB
/EXPORT
/INCLUDE
/MANIFESTDEPENDENCY p >
/MERGE
/SECTION
(1)/DEFAULTLIB:library
/DEFAULTLIB 옵션은 참조를 확인할 때 검색할 라이브러리를 LINK에 추가합니다. 도서관 목록. /DEFAULTLIB로 지정된 라이브러리는 명령줄에 지정된 라이브러리 뒤, obj 파일에 지정된 기본 라이브러리 이전에 검색됩니다.
모든 기본 라이브러리(/NODEFAULTLIB) 옵션을 무시하고 /DEFAULTLIB:library를 재정의합니다. 동일한 라이브러리 이름이 둘 다에 지정된 경우 라이브러리 무시(/NODEFAULTLIB:library) 옵션이 /DEFAULTLIB:library를 재정의합니다.
(2)/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]
이 옵션을 사용하면 프로그램에서 함수를 내보내 다른 프로그램이 사용할 수 있도록 할 수 있습니다. 함수를 호출할 수 있고 데이터를 내보낼 수도 있습니다. 내보내기는 일반적으로 DLL에 정의됩니다.
entryname은 호출 프로그램에서 사용할 함수 또는 데이터 항목의 이름입니다.
서수는 1에서 65535 사이의 값을 갖는 내보내기 테이블의 인덱스입니다. 서수가 지정되지 않은 경우 LINK는 하나를 할당합니다. NONAME 키워드는 항목 이름 없이 함수를 일련 번호로만 내보냅니다. DATA 키워드는 내보낸 항목이 데이터 항목임을 지정합니다. 클라이언트 프로그램의 데이터 항목은 extern __declspec(dllimport)을 사용하여 선언되어야 합니다.
정의를 내보내는 방법에는 세 가지가 있으며 권장 사용 순서는 다음과 같습니다.
소스 코드의 __declspec(dllexport)
.def 파일 EXPORTS 문
/LINK 명령의 EXPORT 지정
세 가지 방법 모두 동일한 프로그램에서 사용할 수 있습니다. 또한 LINK는 빌드 프로세스 중에 .exp 파일이 사용되지 않는 한 내보내기가 포함된 프로그램을 빌드할 때 가져오기 라이브러리를 만듭니다.
LINK은 수정된 형식의 식별자를 사용합니다. 컴파일러는 obj 파일을 생성할 때 식별자를 장식합니다. 소스 코드에 있는 것처럼 수정되지 않은 형식으로 링커에 항목 이름을 지정하면 LINK는 해당 이름과 일치하려고 시도합니다. 일치하는 고유한 이름을 찾을 수 없으면 LINK는 오류 메시지를 표시합니다. 링커에 식별자를 할당해야 하는 경우 Dumpbin 도구를 사용하여 식별자의 수정된 이름 형식을 가져옵니다.
(3)/INCLUDE:symbol
/INCLUDE 옵션은 링커에게 지정된 기호를 기호 테이블에 추가하도록 지시합니다. 여러 기호를 지정하려면 기호 이름 사이에 쉼표(,), 세미콜론(;) 또는 공백을 입력합니다. 명령줄에서 각 기호에 대해 /INCLUDE:symbol을 한 번씩 지정합니다.
링커는 기호 정의가 포함된 개체를 프로그램에 추가하여 기호를 확인합니다. 이 기능은 프로그램에 연결되지 않는 라이브러리 개체를 추가하는 데 유용합니다.
이 옵션으로 지정된 기호는 /OPT:REF를 통한 기호 제거보다 우선 적용됩니다.
(4)/MANIFESTDEPENDENCY:manifest_dependent
/MANIFESTDEPENDENCY를 사용하면 매니페스트 파일에 있는 섹션의 속성을 지정할 수 있습니다. /MANIFESTDEPENDENCY 정보는 다음 두 가지 방법으로 LINK에 전달될 수 있습니다.
명령줄에서 직접 /MANIFESTDEPENDENCY를 실행
#pragma 주석을 통해
(5) /MERGE :from=to
/MERGE 옵션은 첫 번째 세그먼트(from)와 두 번째 세그먼트(to)를 결합하고 결합된 세그먼트의 이름을 to로 지정합니다.
두 번째 세그먼트가 존재하지 않으면 LINK는 세그먼트 이름을 (from) to의 이름으로 바꿉니다.
/MERGE 옵션은 VxD를 생성하고 컴파일러에서 생성된 섹션 이름을 다시 쓰는 데 유용합니다.
(6)/SECTION:name,[[!]{DEKPRSW}][,ALIGN=#]
/SECTION 옵션은 섹션의 속성을 변경하는 데 사용됩니다. 지정된 섹션이 있는 경우 obj 파일이 컴파일될 때 세그먼트의 속성 세트가 다시 작성됩니다.
이식 가능한 실행 파일(PE)의 섹션은 새 실행 파일(NE)의 세그먼트 또는 리소스와 거의 동일합니다.
섹션에는 코드나 데이터가 포함됩니다. 세그먼트와 달리 섹션은 크기 제한이 없는 연속적인 메모리 블록입니다. 일부 세그먼트의 코드나 데이터는 프로그램에서 직접 정의하고 사용하는 반면, 일부 데이터 세그먼트는 링커 및 라이브러리 관리자(lib.exe)에 의해 생성되고 운영 체제에 대한 중요한 정보를 포함합니다.
/SECTION 옵션의 이름은 대소문자를 구분합니다.
다음 이름은 표준 이름과 충돌하므로 사용하지 마십시오. 예를 들어 .sdata는 RISC 플랫폼에서 사용됩니다.
.arch
.bss
.data
.edata
.idata
< p>.pdata.rdata
.reloc
.rsrc
.sbss
.sdata< /p>
.srdata
.text
.xdata
세그먼트에 대해 하나 이상의 속성을 지정합니다. 속성은 대소문자를 구분하지 않습니다. 세그먼트의 경우 원하는 모든 속성을 지정해야 합니다. 속성이 지정되지 않으면 이 속성이 없는 것으로 간주됩니다. R, W, E를 지정하지 않으면 기존 읽기, 쓰기 또는 실행 가능 상태가 변경되지 않습니다.
속성에 부정적인 의미를 부여하려면 속성 앞에 느낌표(!)를 추가하세요.
E: 실행 가능
R: 읽기 가능
W: 쓰기 가능
S: 로드용 세그먼트의 이미지는 모든 프로세스에서 공유됩니다.
D: 삭제 가능
K: 캐시 불가능
P: 페이징 불가능
p>K와 P는 부정적인 의미를 나타냅니다.
PE 파일의 섹션에 E, R 또는 W 속성 세트가 없으면 해당 섹션은 유효하지 않습니다.
ALIGN=# 옵션을 사용하면 특정 세그먼트에 대한 정렬 값을 지정할 수 있습니다.
user: 일반 주석을 개체 파일에 넣습니다. 이 옵션은 링커에서 무시됩니다.
9.#pragma 섹션. 세그먼트를 생성합니다.
형식은 다음과 같습니다. #pragma section( "section-name" [, attribute] )
Section-name은 필수 옵션이며 섹션 이름을 지정하는 데 사용됩니다. 이 이름은 표준 섹션의 이름과 충돌할 수 없습니다. 표준 섹션 이름 목록을 보려면 /SECTION을 사용합니다.
속성은 선택사항이며 세그먼트의 속성을 지정하는 데 사용됩니다. 사용 가능한 속성은 다음과 같습니다. 여러 속성은 쉼표(,)로 구분됩니다.
읽기: 읽기 가능
쓰기: 쓰기 가능
실행: 실행 가능
shared: 이 세그먼트의 이미지를 로드하는 모든 프로세스에서 공유
nopage: 페이징할 수 없으며 주로 Win32 장치 드라이버에서 사용됨
nocache: 캐시할 수 없으며 주로 Win32 장치 드라이버에서 사용됨 Win32 장치 드라이버
폐기: 삭제 가능, 주로 Win32 장치 드라이버에 사용됨
제거: 메모리에 상주하지 않음, 가상 장치 드라이버(VxD)에서만 사용됨
속성을 지정하지 않으면 기본 속성은 읽기 및 쓰기입니다.
세그먼트를 생성한 후 __declspec(allocate)을 사용하여 세그먼트에 코드나 데이터를 넣습니다.
예:
//pragma_section.cpp
#pragma section("mysec",read,write)
int j = 0;
__declspec(allocate("mysec"))
int i = 0;
int main(){}
이 예에서는 "mysec" 세그먼트가 생성되고 읽기 및 쓰기 속성이 설정됩니다. 그런데 j는 이 세그먼트에 넣지 않고 __declspec(allocate);을 사용하여 선언하지 않았기 때문에 기본 데이터 세그먼트에 넣었고, i는 __declspec(allocate) 문을 사용하여 선언했기 때문에 이 세그먼트에 넣었습니다.
10. #pragma push_macro 및 #pragma pop_macro. 전자는 지정된 매크로를 스택에 푸시합니다. 이는 나중에 사용하기 위한 임시 저장소와 같습니다. 후자는 스택 상단에 매크로를 팝하고 팝된 매크로는 동일한 이름으로 현재 매크로를 덮어씁니다.
예:
#include
#define X 1
#define Y 2
int main() {
< p>printf("%d",X);printf("\n%d",Y);
#define Y 3 // C4005
< p> #pragma push_macro("Y")#pragma push_macro("X")
printf("\n%d",X);
#define X 2 // C4005
printf("\n%d",X);
#pragma pop_macro("X")
printf("\n%d",X);
#pragma pop_macro("Y")
printf("\n%d",Y);
< p>}출력 결과:
1
2
1
2
1
3