#pragma是C语言留给编译器厂商进行扩展用的。

这个关键字在不同的编译器之间也许是不能够移植的。

#pragma简介

第24课   #pragma使用分析-LMLPHP

#pragma message

第24课   #pragma使用分析-LMLPHP

#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 ;
}

编译命令如下:

第24课   #pragma使用分析-LMLPHP

可见,在编译期间,预处理器处理#pragma message,并输出信息。

将上述程序用vc编译器进行编译,结果如下:

第24课   #pragma使用分析-LMLPHP

输出和gcc只有略微的差别。

bcc32的编译输出如下:

第24课   #pragma使用分析-LMLPHP

#pragma once

第24课   #pragma使用分析-LMLPHP

左边是通过判断宏是否已经定义的方式保证代码只被嵌入一次,预处理器还是处理了这个文件。而#pragma once 保证只处理这个要包含的文件一次。所有pragma once的效率会高一点。

工程中用的比较多的是ifndef方式,而不是pragma方式,因为并不是所有的编译器都支持pragma once。而ifndef是C语言支持的。

pragma once使用示例:

test.c

 #include <stdio.h>
#include "global.h"
#include "global.h" int main()
{
printf("g_value = %d\n", g_value); return ;
}

global.h

 #pragma once

 int g_value = ;

gcc编译运行结果如下:

第24课   #pragma使用分析-LMLPHP

注释掉pragma once后,gcc就会报重定义错误。

vc2010编译运行结果如下:

第24课   #pragma使用分析-LMLPHP

bcc32的编译如下:

第24课   #pragma使用分析-LMLPHP

可见bcc并不支持pragma once。预处理器不支持的pragma参数,会直接删除pragma once这一行。

工程中可以使用以下的解决方案:

第24课   #pragma使用分析-LMLPHP

这样可以保证只包含一次,又保证效率。在不支持pragma once的编译器中,还有ifndef做保证。在支持pragma once 的编译器中,它就起作用了,保证文件只被包含一次,也只被处理一次。

pragma pack:

第24课   #pragma使用分析-LMLPHP

示例程序:

第24课   #pragma使用分析-LMLPHP

运行结果如下:

第24课   #pragma使用分析-LMLPHP

两个结构体的成员是一样的,顺序不一样,占用的空间大小就不一样,这就是内存对齐的结果。

内存排列的结果:

第24课   #pragma使用分析-LMLPHP

内存对齐:

第24课   #pragma使用分析-LMLPHP

第24课   #pragma使用分析-LMLPHP

将上述程序加上pragma pack对齐,如下:

第24课   #pragma使用分析-LMLPHP

再次编译运行,结果如下:

第24课   #pragma使用分析-LMLPHP

现在两个结构体占用的内存大小就是一样的了。

第24课   #pragma使用分析-LMLPHP

再次给出一个示例程序:

 #include <stdio.h>

 #pragma pack(8)

 struct S1
{
short a;
long b;
}; struct S2
{
char c;
struct S1 d;
double e;
}; #pragma pack() int main()
{
printf("%d\n", sizeof(struct S1));
printf("%d\n", sizeof(struct S2)); return ;
}

手工分析的对齐结果如下:

第24课   #pragma使用分析-LMLPHP

运行结果如下:

第24课   #pragma使用分析-LMLPHP

和我们手工计算的结果并不一样。这是因为gcc编译器不支持8字节对齐,在遇到#pragma pack(8)的时候就直接给删除了。然后就按照默认的4字节对齐了。

在vc编译器下的编译运行结果如下:

第24课   #pragma使用分析-LMLPHP

这个运行结果和我们手工分析的一样,说明了不同的编译器对pack中的大小支持也是不一样的。

小结:

第24课   #pragma使用分析-LMLPHP

05-07 15:44