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号警告信息。