#pragma用於指示完成一些特定的動作,並且所定義的很多指示字是編譯器特有的。
#pragma在不同的編譯器間是不可移植的:
——預處理器將忽略它不認識的#pragma指令
——不同的編譯器可能以不同的方式解釋一條#pragma指令。
一般用法:
#pragma parameter
注:不同的parameter參數語法和意義各不相同
message參數在大多數的編譯器中都有相似的實現;message參數在編譯時輸出消息到編譯輸出窗口中。
與#error和#warning不同,#pragma message僅僅代表一條編譯消息,不代表程序錯誤。
#include <stdio.h>
#if defined(ANDROID20)
#pragma message("Compile Android SDK 2.0...")
#define VERSION "Android 2.0"
#elif defined(ANDROID23)
#pragma message("Compile Android SDK 2.3...")
#define VERSION "Android 2.3"
#elif defined(ANDROID40)
#pragma message("Compile Android SDK 4.0...")
#define VERSION "Android 4.0"
#else
#error Compile Version is not provided!
#endif
int main()
{
printf("%s\n", VERSION);
return 0;
}
在Linux下使用GCC進行編譯:
~/will$ gcc 24-1.c //直接編譯
24-1.c:13: error: #error Compile Version is not provided!
24-1.c: In function ‘main’:
24-1.c:18: error: ‘VERSION’ undeclared (first use in this function)
24-1.c:18: error: (Each undeclared identifier is reported only once
24-1.c:18: error: for each function it appears in.)
~/will$
~/will$
~/will$ gcc -DANDROID23 24-1.c // 條件編譯
24-1.c:7: note: #pragma message: Compile Android SDK 2.3... //與VC不同的是,BCC和GCC將 #pragma message: 打印出來
~/will$
~/will$
~/will$ ./a.out //運行
Android 2.3
#pragma once
#pragma once 用於保證頭文件紙杯編譯一次;#pragma once 是編譯器相關,不一定被支持。
pragma once是部分編譯器支持;預處理器遇見pragma once後將直接忽略再次出現的頭文件
#pragma pack 內存對齊
——不同類型的數據在內存中按照一定的規則排列
——而不一定是順序的一個接一個的排列
爲什麼需要內存對齊?
——CPU對內存的讀取不是連續的,而是分成塊讀取的,快的大小隻能是1,2,4,8,16...字節;
——當讀取操作的數據未對齊,則需要兩次總線週期來訪問內存,因此性能會大打折扣;
——某些硬件平臺只能從規定的相對地址處讀取特定類型的數據,否則產生硬件異常。
#pragma pack用於指定“內存對齊”方式。
#include <stdio.h>
#pragma pack(4)
struct Test1
{ //對齊參數 偏移地址 大小
char c1; //1 0 1(4)
short s; //2 2 2
char c2; //1 4 1(4)
int i; //4 8 4
};
#pragma pack()
#pragma pack(4)
struct Test2
{ //對齊參數 偏移地址 大小
char c1; //1 0 1
char c2; //1 1 1
short s; //2 2 2
int i; //4 4 4
};
#pragma pack()
int main()
{
printf("sizeof(Test1) = %d\n", sizeof(struct Test1));
printf("sizeof(Test2) = %d\n", sizeof(struct Test2));
return 0;
}
編譯運行:
~/will$ ./a.out
sizeof(Test1) = 12
sizeof(Test2) = 8
Gcc編譯器暫時不支持8字節對齊。
struct佔用的內存大小:
——第一個成員起始於0偏移處;
——每個成員按其類型大小和pack參數中較小的一個進行對齊;
偏移地址必須能被對齊參數整除;
結構體成員的大小取其內部長度最大的數據成員作爲其大小;
結構體總長度必須爲所有對齊參數的整數倍
注意:編譯器在默認情況下按照4字節對齊。#include <stdio.h>
#pragma pack(8)
struct S1
{ //對齊參數 偏移地址 大小
short a; //2 0 2
long b; //4 4 4
};
struct S2
{ //對齊參數 偏移地址 大小
char c; //1 0 1
struct S1 d; //4 4 8
double e; //8 16 8
};
#pragma pack()
int main()
{
printf("%d\n", sizeof(struct S1));
printf("%d\n", sizeof(struct S2));
return 0;
}
Gcc編譯器暫時不支持8字節對齊,輸出爲8
20
在vc編譯器支持8字節對齊,輸出爲8
24
小結:
#pragma用於指示編譯器完成一些特定的動作
#pragma所定義的很多指示字是編譯器特有的
——#pragma message用於自定義編譯消息——#pragma once用於保證頭文件只被編譯一次
——#pragma pack用於指定內存對齊方式