zoukankan      html  css  js  c++  java
  • c语言学习笔记---预编译

    专题三:

    1)       预编译

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

    将所有的#define删除,并且展开所有的宏定义,

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

    处理#include,展开呗包含的文件,

    保留编译器需要使用的#pragma指令,

    预处理指令:gcc-E file.c –o hello.i

    编译:

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

    语法分析主要分析关键字,表示符,立即数是否合法,语法分析主要分析表达式是否遵循语法规则

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

    分析结束后进行代码优化生成相应的汇编代码文件

    编译指令:gcc –s file.c –o hello.s

    汇编:汇编器将汇编代码转变为机器可以执行的指令,

    每个汇编句几乎都对应一条机器指令

    汇编指令:gcc –c file.s –o hello.o

    链接器的意义

    连接器的主要作用是各个模块之间相互引用的部分处理好,

    使得各个模块之间能够正确的衔接。

    模块拼装:  静态链接,(file1.o,file2.o,libc.a)-à链接器(linker)-àa.out

    动态链接:file1.cà编译器(gcc)àfile1.oà连接器(linker)àa.out

    Lib1.soàstub1à连接器(linker)àa.out

    Lib2.soàstub2à链接器(linker)àa.out

    编译器将编译工作主要分为预处理,编译和汇编三部

    连接器的工作是各个独立的模块链接为可执行程序,

    静态链接在编译期完成,动态链接在运行期完成,

    2)宏定义与使用分析:

       定义宏常量:

      #define定义宏常量可以出现代码的任何地方

      #define从本行开始,之后的代码都可以使用这个宏常量

      #define ERROR  -1

      #define PI      3.1415926

      #define PATH_2  “D:DelphiCTopic3.ppt”

    #define PATH_1  D:DelphiCTopic3.ppt

    #define PATH_3  D:Delphic

    Topic3.ppt

    顶哟宏表达式

    #define 表达式给有函数调用的假象,却不是函数,

    #define表达式可以比函数更强大

    #define 表达式比函数更容易出错

    #define SUM(a,b) (q)+(b)

    #define MIN(a,b) ((a)<(b)? (a):(b))

    #define DIM(a) () (sizeof (a)/sizeof(*a))

    以上宏表达式有没有问题?完全等价函数吗?

    宏表达式与函数的对比

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

    宏表达式用”实参”完全替代形参,不进行任何运算,

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

    宏表达式不能出现定义

    #define FAC(n) ((n>0)? (FAC(n-1)+1):0)

    Int  j=FAC(100);

    宏定义的常量或表达式是否有作用或限制

    Int f1(int  a, int  b)

    {

        #define MIN(a,b) ((a)<(b)?a:b)

       Return MIN(a,b);

    }

    Int f2 (int a,int b,int c)

    {

    Return MIN (MIN(a,b),c);

    }

    Int main ()

    {

    Printf (“%d ”,f1(2,1));

    Printf(“%d ”,f2(5,3,2));

    Return 0;

    }

    强大的内置宏,

    _FILE_------被编译的文件名-----file1.c

    _LINE_------当前行号---25

    _DATE_-------编译时的日期------Jan 31 2012

    _TIME_ -------编译时的时间 ----17:01:01

    _STDC_ -------编译器是否遵循标准C规范—1

    定义日志宏

    #define f(x)  ((x)-1)

    上面的宏定义代表什么意思

    宏定义对空格没敢吗?宏”调用”对空格敏感吗?

    条件编译使用分析

    条件编译的行为类似于C语言中的if…else

    条件编译是预编译指示命令,用于控制是否编译某段代码

    #define c1

    Int main()

    {

       #if(c==1)

    Printf(“This is first printf … ”);

    #else

    Printf(“This is second printf … ”);

    #endif

    Return 0;

    }

    #include 的困惑

    #include 的本质将已经存在的文件内容嵌入到当前文件中,

    #include的间接包含同样会产生嵌入文件内容的动作

    条件编译的意义

    条件编译使得我们可以按不同的条件不同代码段,因而可以产生不同的目标代码

    #if…#else…#endif被预编译器处理;而if…else语句被编译器处理,必然被编译进目标代码

    实际工程条件编译主要用于一下两种情况:

    不同的产品线共用一份代码

    区分编译产品的调试版和发布版

    总:小结

    条件编译的使用:

    通过编译器命令行能够定义预处理器使用的宏

    条件编译可以避免重复包含头同一头文件,

    条件编译是在工程开发中可以区别不同产品线的代码,

    条件编译可以定义产品的发布版和调试版

    #error的用法:

    #error用于生成一个编译错误的消息,并停止编译;

    用法:#error message 注:message 不需要用双引号围,

    #error编译指示字用于自定义程序员特有的编译错误消息类似的,#warning 用于生成编译警告,但不会停止编译。

    #error 和 #warning的使用:自定义错误消息

    #line的用法:

    #line用于强制指定新的行号和编译文件名,并对源程序的代码重新编号

    用法:

          #line number filenames 注:filename 可省略

    #line 编译指示字的本质是重定义_LINE_和_FILE_

    #pragma预处理分析:#pragma是编译器指示字,用于指示编译器完成一些特定的动作,

    #pragma 所定义的很多指示字是编译器和操作系统特有的,

    #pragma 在不同的编译器间是不可移植的

       预处理器将忽略它不认识的#pragma指令,

        两个不同的编译器可能以两种不同的方式解释同一条#pragma指令,

                一般用法:#pragma parameter 注:不同的Parameter参数语法和意义 各不相同的

    #pragma message :

    message参数在大多数的编译器中都有相似的实现,

    message参数在编译时输出消息到编译输出窗口中,

    message可用域代码的版本控制,注:message是VC特有的编译器指示字,GCC中将其忽略。

    #pragma 在不同编译器下的使用示例:

    #pragma pack

    什么是内存对齐?

    不同类型的数据在内存中按照一定的规则排列;而不是数序的一个接一个的排放,这就是对齐

         struct Test1

            {

                char c1;

                short s;

                char c2;

               int i; 

               }

            struct Test2

           {

          char c1;

          char c2;

           short s;

            int i;

            }

      两种类型所占的内存空间是否相同?

    #pragma pack

     为什么需要i内存对齐?

      cpu对内存的读取不是连续的,而是分成块读取的,块的大小只能是1、2、4、8、16字节

    当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此性能会大打折扣。

    某些硬件平台只能从规定的地址处去某些特定类型的数据,否则抛出硬件异常。

     #pragma pack

    #pragma pack 能够改变编译器的默认对i去方式

      #pragma pack (2)                     #pragma  pack(4)

          struct Test1                                    struct Test2

            {                                                    {

                char c1;                                       char c1;

                short s;                                        char c2;

                char c2;                                        short s;

               int i;                                                int i;

              }                                                   }

    #pragma pack ()                               #pragma pack()

    sizeof(struct Test1)=?

    sizeof(struct Test2)=?

    #pragma pack:

    struct  占用的内存大小

       第一成员起始于0偏移处,

       每个成员按其类型大小和指定对齐参数n中较小的一个进行对齐,

         偏移地址和成员占用大小均需对齐

         结构体成员的对齐参数为其所有成员使用的对其参数的最大值

    结构体总长度必须为所有对齐参数的整数倍,

    课后思考:

    结构体变量是否可以直接用memcmp函数进行相等判断?为什么?

    #和##晕窜使用解析:

    #运算符:

    #运算符用于在预编译期将宏参数转为字符串

         #include <stdio.h>

            #define CONVERS(x) #x

      int main ()

             {

                printf ("%s ",CONERS(Hello world!));

               printf ("%s ",CONVERS(100));

               printf ("%s ",CONVERS(while));

               printf("%s ",CONVERS(return));        

              return 0;  

          }

    #运算符在宏中的妙用:

    ## 运算符:

    ##运算符用于在预编译期粘连两个符号

       #include<stdio.h>

      #define NAME (n) name##n

     int main()

    {

         int NAME (1);

         int  NAMR(2);

        

          NAME (1)=1;

          NAME(2)=2;

         

          printf ("%d ",NAME(1));

           printf("%d ",NAME(2));

          return 0;

    }

    利用##定义结构类型:

            

  • 相关阅读:
    关于COM+的一些回顾
    Workflow Foundation 4.0中的事件驱动流程设计和应用(四)
    html5及其相关学习资源介绍
    ADO.NET Data Service如何直接支持用Json格式返回数据
    《实践与思考》系列连载(5)——问答Hprose,以及关于技术与开源的思考
    .NET Framework 4新特性之 Type Equivalence(等价类型)
    做软件也是要有点追求的
    Console的默认Encoding问题
    《实践与思考》系列连载(6)——IT从业人员工作环境及状态调查 抽奖结果公布
    Workflow Foundation 4.0中的事件驱动流程设计和应用(一)
  • 原文地址:https://www.cnblogs.com/dpf-learn/p/6107981.html
Copyright © 2011-2022 走看看