1.编译过程的简介:


.net 预编译 预编译处理_字符串

 预编译:

a.处理所有的注释,以空格代替。

b.将所有#define删除,并展开所有的宏定义,字符串替换。

c.处理条件编译指令#if,#ifdef,#elif,#else,#endif

d.处理#include,并展开被包含的文件,把头文件中的声明,全部拷贝到文件中。

e.保留编译器需要使用的#pragma指令、

gcc file.c -o file.i -E生成预处理过的文件

编译:

a.对预处理文件进行一系列词法分析,语法分析和语义分析

                词法分析:主要分析关键字,标示符,立即数等是否合法

                语法分析:主要分析表达式是否遵循语法规则

                语义分析:在语法分析的基础上进一步分析表达式是否合法

编译指令:gcc -S  file.c  -o  file.s

汇编:

汇编指令:gcc  -c  file.c  -o file.o  注意:-c是编译汇编不连接。

   链接:

连接指令:gcc  file.o  file1.o  -o  file  这句指令是链接file.o和file1.o两个编译并汇编的文件,并生成可执行文件file。

链接分两种:静态链接和动态链接,静态链接是在编译器完成的,动态链接是在运行期完成的。静态链接的指令是:gcc -static file.c -o file对于一些没有动态库的嵌入式系统,这是常用的。

gcc file.c  -o  file



2.c语言中的预处理指令:#define、#undef(撤销已定义过的宏名)、#include、#if、#else、#elif、#endif、#ifdef、#ifndef、#line、#error、#pragma。还有一些ANSI标准C定义的宏:__LINE__、__FILE__、__DATA__、__TIME__、__STDC__。这样使用printf("%s\n",__TIME__);     printf(__DATE__);

一个#undef的例子:

1. #include <stdio.h>  
2. #include <stdlib.h>  
3. #include <string.h>  
4.   
5.   
6. #define X 2  
7. #define Y X*2  
8. #undef X  
9. #define X 3  
10.   
11.   
12. int main()  
13. {  
14. "%d\n",Y);  
15. return 0;  
16. }

这个输出的是6,说明了#undef的作用

还有就是一切宏都是不能有分号的,这个一定要切忌!!!

4.宏与函数的比较:

   a.宏表达式在预编译期被处理,编译器不知道有宏表达式存在

   b.宏表达式没有任何的"调用"开销

   c.宏表达式中不能出现递归定义


为什么不在头文件中定义全局变量:

如果一个全局变量,想要在两个文件中,同时使用,那这两个文件中都应该#include这个头文件,这样的话就会出现重复定义的问题。其实是重名的问题,因为#include是分别在两个文件中展开的,试想一下,如果在两个文件中的开始部分,都写上int  a = 10;  是不是也会报错。可能你会说那个#ifndef不是防止重复定义吗?是的 ,那是防止在同一个文件中,同时出现两次这个头文件。现在是两个文件中,所以都要展开的。全局变量就重名了!!!所以 对于全局变量,最好是定义在.c文件中,不要定义在头文件中。

6.#pargma pack 设置字符对齐,看后面一节专门写字符对齐问题的!!!



7.#运算符(转换成字符串):

    假如你希望在字符串中包含宏参数,那我们就用#号,它把语言符号转换成字符串。

    #define SQR(x) printf("the "#x"lait %d\n",((x)*(x)));
    SQR(8)
    输出结果是:the 8 lait 64   这个#号必须使用在带参宏中

有个小例子:

1. #include <stdio.h>  
2. #include <stdlib.h>  
3. #include <string.h>  
4. /*在字符串中  加入宏参用的*/  
5. #define SCAN(N,String) scanf("%"#N"s",String);  //N是截取的个数  String是存储的字符串   
6. int main()  
7. {  
8. char dd[256];  
9. //记得没有分号哈  自定义 任意格式输入的scanf  截取输入的前三个   
10. "%s\n",dd);  
11. return 1;  
12. }

8.##运算符(粘合剂)

    一般用于粘贴两个东西,一般是用作在给变量或函数命名的时候使用。如#define XNAME(n) x##n

    XNAME(8)为8n   这个##号可以使用在带参宏或无参宏中

下面是一个##运算符的小例子,代码如下:


1. #include <stdio.h>  
2. #include <stdlib.h>  
3. #include <string.h>  
4.   
5. #define BL1 bb##ll##1  
6.   
7. #define BL(N) bbll##N  
8. int main()  
9. {  
10. int BL1=10;  
11.   
12. int BL(4)=15;  
13. "%d\n",bbll1);  
14.       
15. "%d\n",bbll4);  
16. return 1;  
17. }

注意:#号和##号都必须只能在宏定义中使用,不能使用在其他地方

9.其实预编译这块还有一些,不常用到的预编译指令,也是盲点,但是不难理解,用到的时候查查就好。比如说#line、#error、#warning等。