#pragma是C语言留给编译器厂商进行扩展用的。
这个关键字在不同的编译器之间也许是不能够移植的。
#pragma简介
#pragma message
#pragma message打印的消息并不代表代码有什么问题。
示例:
1 #include <stdio.h> 2 3 #if defined(ANDROID20) 4 #pragma message("Compile Android SDK 2.0...") 5 #define VERSION "Android 2.0" 6 #elif defined(ANDROID23) 7 #pragma message("Compile Android SDK 2.3...") 8 #define VERSION "Android 2.3" 9 #elif defined(ANDROID40) 10 #pragma message("Compile Android SDK 4.0...") 11 #define VERSION "Android 4.0" 12 #else 13 #error Compile Version is not provided! 14 #endif 15 16 int main() 17 { 18 printf("%s ", VERSION); 19 20 return 0; 21 }
编译命令如下:
可见,在编译期间,预处理器处理#pragma message,并输出信息。
将上述程序用vc编译器进行编译,结果如下:
输出和gcc只有略微的差别。
bcc32的编译输出如下:
#pragma once
左边是通过判断宏是否已经定义的方式保证代码只被嵌入一次,预处理器还是处理了这个文件。而#pragma once 保证只处理这个要包含的文件一次。所有pragma once的效率会高一点。
工程中用的比较多的是ifndef方式,而不是pragma方式,因为并不是所有的编译器都支持pragma once。而ifndef是C语言支持的。
pragma once使用示例:
test.c
1 #include <stdio.h> 2 #include "global.h" 3 #include "global.h" 4 5 int main() 6 { 7 printf("g_value = %d ", g_value); 8 9 return 0; 10 }
global.h
1 #pragma once 2 3 int g_value = 1;
gcc编译运行结果如下:
注释掉pragma once后,gcc就会报重定义错误。
vc2010编译运行结果如下:
bcc32的编译如下:
可见bcc并不支持pragma once。预处理器不支持的pragma参数,会直接删除pragma once这一行。
工程中可以使用以下的解决方案:
这样可以保证只包含一次,又保证效率。在不支持pragma once的编译器中,还有ifndef做保证。在支持pragma once 的编译器中,它就起作用了,保证文件只被包含一次,也只被处理一次。
pragma pack:
示例程序:
运行结果如下:
两个结构体的成员是一样的,顺序不一样,占用的空间大小就不一样,这就是内存对齐的结果。
内存排列的结果:
内存对齐:
将上述程序加上pragma pack对齐,如下:
再次编译运行,结果如下:
现在两个结构体占用的内存大小就是一样的了。
再次给出一个示例程序:
1 #include <stdio.h> 2 3 #pragma pack(8) 4 5 struct S1 6 { 7 short a; 8 long b; 9 }; 10 11 struct S2 12 { 13 char c; 14 struct S1 d; 15 double e; 16 }; 17 18 #pragma pack() 19 20 int main() 21 { 22 printf("%d ", sizeof(struct S1)); 23 printf("%d ", sizeof(struct S2)); 24 25 return 0; 26 }
手工分析的对齐结果如下:
运行结果如下:
和我们手工计算的结果并不一样。这是因为gcc编译器不支持8字节对齐,在遇到#pragma pack(8)的时候就直接给删除了。然后就按照默认的4字节对齐了。
在vc编译器下的编译运行结果如下:
这个运行结果和我们手工分析的一样,说明了不同的编译器对pack中的大小支持也是不一样的。
小结: