第24课 #pragma使用分析

#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中的大小支持也是不一样的。

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9537245.html