20170214C语言提升07_预编译指令

来源:互联网 发布:单晶叶片 知乎 编辑:程序博客网 时间:2024/05/21 19:39

预编译指令:

条件编译指令:属于编译环境和编译器之间的交流指令,预编译指令控制的是代码。
#include <stdio.h>#define DEMO 5#ifndef DEMO//如果没有定义DEMO做的事情int num = 0;#endif // !DEMO#ifdef DEMO//如果定义了DEMO要做的事情int num = 100;#endif // !DEMO//int main(){printf("%d", num);#if (DEMO==0)//这里条件必须是使用预编译时候就有的条件,不可以使用num等变量。num要与处理完之后才有的。printf("DEMO == 0\r\n");#elif(DEMO == 1)printf("DEMO == 1");#elseprintf("DEMO!=0 && DEMO!=1");#endifreturn 0;}

如果两个.h文件互相包含,main.c里面包含任何一个.h,编译的时候就会导致递归,包含了无穷个.h。这种情况就是用宏来做
#ifndef 
#define
#endif
用这个来防止一个库文件被多次包含。
宏定义还可以在属性里面的预处理器和命令行里面进行添加,命令行里面可以给宏定义赋值。

错误提示预编译指令:

用在编译的时候提示错误。
#include <stdio.h>#define ERRORint main(){#ifdef ERROR#error You Are Error#endifprintf("222");return 0;}

上面这段代码再便宜的时候就会提示出错误,并打印#error后面的文字。多用于多人协作的时候使用。
#warning已被遗弃,用法差不多的。

设置文件名及行号:

将对应地点的行号进行设置,文件名也对应设置
#include <stdio.h>#line 100 "main.c"int main(){printf("%s中的第%d行", __FILE__, __LINE__);return 0;}

#line后面的第一个数字代表当前行的下一行行号被设置成这个数,后面的字符串代表文件名被改成这个名字。

版本控制利器#Pragma message:

1:特殊的预编译指令:实际叫做预编译指示字。
2:#pragma是一个指示字,不同的C语言编译器对他的理解是不同的,这个是没有标准的。
3:它不具有移植性,但是如果一个编译器发现了一个他没有定义的预编译指示字的时候,他会忽略。不影响移植性。
4:他并非作用于代码,它主要的作用是指示编译器来完成特殊的指令。
#include <stdio.h>#define VER 1#if(VER == 1)#pragma message("版本1.0")//message指示字是VS特有的。这些并不作用于代码,只是在编译的时候输出信息#endifint main(){return 0;}

BAT名企敲门砖-高端面试之内存对齐:

1:#pragma pack(2)//内存对齐控制指示字,里面的数字必须为1 2 4 8 16 32。
2:内存对齐是为了方便cpu对数据的读取,cpu是按照块来读取的。
    注意:有的cpu可能只会从偶数位的地址开始读取,如果为奇数,可能报硬件错误。
3:默认的对其方式是4。程序编译器对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。
4:对其的时候,会首选较小的数据类型扩大。例如默认的对齐方式是4byte,如果一个结构体为struct s1 {short s;int n;};,那么他占用空间为8byte,short为前2byte,空2byte,后四个为int。这种更方便cpu读取。具体准确规则比较复杂,通过下面的例子来看
#include <stdio.h>//内存的对齐方式控制的指示字#pragma pack(4)//里面跟的数字必须为1 2 4 8 16  数据对齐方式struct s1 {short s;//2byteint n;//4bytechar c;};struct s2 {char c;//1bytestruct s1 s;//它使用的对齐方式为里面成员使用的对齐参数的最大值 4double d;//8byte};struct s3 //偏移是内存地址的偏移(必须可整除对齐参数),pack是设置的,size是数据类型大小,对齐参数是pack和size取小值,结果为占用内存位置空间{//偏移packsize对齐参数结果char c;//04110int n;//44444-7short s;//84228-9char c1;//1041110long l;//1244412-15double d;//1648416-23};//总长度必须可以整除对齐参数#pragma pack()int main(){printf("%d\r\n", sizeof(struct s1));printf("%d\r\n", sizeof(struct s2));printf("%d\r\n", sizeof(struct s3));struct s3 ss3;ss3.c = 'a'; ss3.c1 = 'b'; ss3.d = 100; ss3.l = 50; ss3.n = 25; ss3.s = 12;return 0;}

奇淫意巧-生态生成变量名:

1:宏定义的时候使用的#号,可以将其他的转化为字符串:
#include <stdio.h>#define ERROR(n) #nint main(){int error_code = 10;printf("%s", ERROR(100));//将打印100return 0;}

2:##的使用:
#include <stdio.h>#define STR(n) #n//#号的使用,转化成字符串#define NO(n) No##n//##的使用,代表连接符/*#define STRUCT(type) typedef struct tag_##type; struct tag_##type;//上课讲了,但运行出错STRUCT(S1){int i;};*/int main(){int error_code = 10;printf("%s", STR(100));//将打印100int NO(1);int NO(2);int NO(3);for (int i = 0; i < 20; ++i){printf("%s\r\n", STR(NO(i)));//这里会打印20个NOi。他只会认里面的直接字。}/*S1 s;s.i = 100;*/return 0;}




1 0
原创粉丝点击