3.4 #error预处理
【注意】宏串error-message不用双引号包围。
3.5 #line预处理
#line number["filename"]
#line的作用是改变当前行数和文件名称。(测试发现,在单步调试运行到#line这行时,会跳转到其所指示的那行代码)
【注释】此命令主要用在编译器的编写中
3.6 #pragma预处理
在所有的预处理指令中,#pragma指令可能是最复杂的了。它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。
#pragma para
常用的一些参数如下:
[1] #pragma message
它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。(测试时,未发现在调试窗口有信息输出?)
#pragma message("消息文本")
[2] #pragma code_seg
它能够设置程序中函数代码存放的代码段,当开发驱动程序的时候就会使用到它。
[3] #pragma once
比较常用。只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。
[4] #pragma hdrstop
表示预编译头文件到此为止,后面的头文件不进行预编译。
[5] #pragma resource
表示把一些资源文件加入到工程中。
[6] #pragma warning
#pragma warning(disable:4507 34; once:4385; error:164)
等价于:
#pragma warning(disable:4507 34) // 不显示4507和34号警告信息
#pragma warning(once:4385) // 4385号警告信息仅报告一次
#pragma warning(error:164) // 把164号警告信息作为一个错误
[7] #pragma comment
#pragma comment(...)表示将一个注释记录放入一个对象文件或可执行文件中。
#pragma comment(lib, "user32.lib")该指令用来将user32.lib库文件加入到本工程中。
[8] #pragma pack
内存对齐的问题。
#pragma pack(n),编译器将按照n个字节对齐。
#pragma pack(),编译器将取消自定义字节对齐方式。
在#pragma pack(n)和#pragma pack()之间的代码,按照n个字节对齐。
【注意】成员对齐有一个重要的条件,即每个成员按自己的方式对齐,也就是说虽然指定了按n字节对齐,但并不是所有的成员都是以n字节对齐。
【对齐规则】每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是n字节)中较小的一个对齐,即:min(n, sizeof(item))。并且,结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。对于结构体成员来说,它的默认对齐方式是它的所有成员使用的对齐参数中最大的一个。
例如:
#pragma pack(8)
struct TestStruck4
{
char a;
long b;
}
struct TestStruck4
{
char c;
TestStruck4 d;
long long e;
};
#pragma pack();
问题:
1) sizeof(TestStruck4) = ?
2) sizeof (TestStruck5) =?
[附加:C语言的C99标准扩展了新的整数类型long long ,long 是32位宽,占4个字节;long long 通常被定义为64位宽,占8字节]
解析:TestStruck4 中,成员a是1字节,默认按1字节对齐,指定对齐参数为8,这两个值中取1(即:min(8,1)),a按1字节对齐;成员b是4字节,(min(8,4)),b按4字节对齐,所以sizeof(TestStruck4) =8
TestStruck4 的内存布局 1xxx,1111
TestStruck5 中,c 按1个字节对齐;d是个结构,默认对齐方式是:所有成员中最大数据的成员的对齐长度,即成员d按4字节对齐;而e是8字节,所以按8字节对齐(以8的倍数为起始地址对齐);
c d.a d.b e
TestStruck5 的内存布局 1xxx,1111,1111,xxxx,1111,1111
所以sizeof(TestStruck5) =24
3.6 #运算符
【问题】#也是预处理?(是的)
- #include <cstdio>
- #define SQR_1(x) printf("The square of x is %d./n",((x)*(x)));
- #define SQR_2(x) printf("The square of #x is %d./n",((x)*(x)));
- #define SQR_3(x) printf("The square of "#x" is %d./n",((x)*(x)));
- int main()
- {
- SQR_1(8);// The square of x is 64.
- SQR_2(8);// The square of #x is 64.
- SQR_3(8);// The square of 8 is 64.
- return 0;
- }
假如我们希望在字符串中包含宏参数,那我们就可以使用"#",它可以把语言符号转化为字符串。
3.8 ##运算符
##也可以用于宏函数的替换部分,这个运算符把两个语言符号组合成单个语言符号。
- #define XNAME_1(n) xn
- #define XNAME_2(n) x##n
- XNAME_1(8);// error, cannot find xn
- XNAME_2(8);// ok, replaced by x8
【结论】##就是一个粘合剂,将前后两部分粘合起来。