2.5 #pragma指令的使用

如果读者认真阅读了本书前面的代码,那么应该对#pragma指令有印象,在之前的代码中曾使用过#pragma指令来设置编译器的字节对齐方式。接下来看看预处理中的#pragma指令,其作用是设置编译器的状态或指示编译器完成一些特定的动作。使用#pragma指令的一般形式为:


pragma para


其中,para为参数。下面对一些常见的参数进行讲解。


(1)#pragma message("消息")


至于“#pragma message("消息")”究竟有什么作用,可以通过下面的一段代码来了解其具体的使用方式。


include<stdio.h>

define STR

void main(int argc,char*argv)

{

printf("学习#pragma命令中message参数的使用!\n");

ifdef STR

pragma message("STR已经定义过了")

endif

return;

}


在Linux环境下使用gcc编译运行的结果:


root@ubuntu:/home#gcc message.c-o msg

message.c:In function'main':

message.c:10:11:note:#pragma message:STR已经定义过了

root@ubuntu:/home#./msg

学习#pragma命令中message参数的使用!


我们发现,在编译的时候会打印出message参数中的信息。通过这种方式,可以在代码中输出想要的信息,也可以看某个宏是否已经被定义过。与之前使用printf()函数实现打印的不同之处在于:message打印消息出现在编译的时候,不会出现在程序最终的运行结果中;而printf()函数的打印消息却会出现在最终的运行结果中。有时候,我们并不希望运行结果中出现与结果无关的信息,这时可以使用#pragma命令,选择message参数来实现信息的打印输出。


(2)#pragma once


如果在头文件的开头部分加入这条指令,那么就能保证头文件只被编译一次。


(3)#pragma hdrstop


该指令表示编译头文件到此为止,后面的无需再编译了。


(4)#pragma pack()


我们在此前的代码中已经接触过这个指令了,但是没有进行详细的讲解。接下来了解使用这个参数的几个典型应用,看看下面的代码。


include<stdio.h>

void main(int argc,char*argv)

{

pragma pack(2)

struct_stu1{

char name[20];

char num[10];

int score;

char sex;

}stu1;

printf("str1占用内存的大小为:%d个字节\n",sizeof(stu1));

pragma pack()

struct_stu2{

char name[20];

char num[10];

int score;

char sex;

}stu2;

printf("str2占用内存的大小为:%d个字节\n",sizeof(stu2));

return;

}


运行结果:


str1占用内存的大小为:36个字节

str2占用内存的大小为:40个字节


在上面的代码中,在结构体st1的前面使用了#pragma pack(2),其作用是设置2字节对齐,接下来使用了#pragma pack(),其作用是取消之前设置的字节对齐方式,采用默认的4字节对齐。在输出结果中,由于stu1在内存中采用2字节对齐,而stu2在内存中采用4字节对齐,所以它们输出的结果不一致。将上面的代码修改为以下的形式。


include<stdio.h>

void main(int argc,char*argv)

{

pragma pack(push)

pragma pack(2)

struct_stu1{

char name[20];

char num[10];

int score;

char sex;

}stu1;

printf("str1占用内存的大小为:%d个字节\n",sizeof(stu1));

pragma pack(pop)

struct_stu2{

char name[20];

char num[10];

int score;

char sex;

}stu2;

printf("str2占用内存的大小为:%d个字节\n",sizeof(stu2));

return;

}


运行结果与前面代码的运行结果完全一致。看看修改的地方,在设置2字节对齐方式之前添加了一句代码“#pragma pack(push)”,其作用是保存当前默认的字节对齐方式,而把下面原本的“#pragma pack()”修改为“#pragma pack(pop)”,其作用是恢复默认的字节对齐方式,可以看出这里代码的功能与之前代码的功能完全一致。

(5)#pragma warning()

“#pragma warning(disable:M N;once:H;error:K)”表示不显示M号和N号的警告信息,H号警告信息只报告一次,把K号警告信息作为一个错误来处理。也可以将其分开来实现,代码如下。


pragma warning(disable:M N)

pragma warning(once:H)

pragma warning(error:K)


这样的实现方式与前面的“#pragma warning(disable:M N;once:H;error:K)”是等价的。也可以使用#pragma warning(enable:N)启用N号警告信息。