从零开始 学习C/C++的第十九天 预处理指令 宏

11.24

11.24

预处理指令:

    程序员所编写的代码并不能被编译器真正编译,需要一段程序把代码翻译一下

    翻译的程序叫做预处理器,翻译的过程叫做预处理,被翻译的语句叫做预处理指令,以#开头的语句都是预处理指令

    查看预处理结果:

        gcc -E xxx.c    把预处理的结果显示到终端

        gcc -E xxx.c -o xxx.i   把预处理的结果存储到.i预处理文件中

    预处理指令的分类:

        #include    导入头文件

        #include <> 从系统指定的路径下查找并导入头文件

        #include "" 先从当前路径下查找头文件,如果找不到再从系统指定路径下查找并导入

        编译参数 -I /path 也可以指定头文件查找路径

        系统通过设置环境变量来指定头文件的系统查找路径

        #define     定义宏

            宏常量

                #define MAX 50

                优点:提高可读性,提高可扩展性(批量修改),提高安全性,还可以与case配合使用      case MAX

                注意:宏常量名建议全部大写,末尾不要加分号

                【函数名,局部变量小写+下划线,全局变量首字母大写,指针变量+p,数组arr,字符串str】

               

            宏函数

                typedef int num;   用法和含义上的区别

           

            预定义好的宏常量:

                __func__    获取函数名

                __FILE__    获取文件名

                __LINE__    获取当前行号

                __DATE__    获取当前日期

                __TIME__    获取当前时间

            宏函数:

                #define SUM(a,b)    a+b

                宏函数其实就是带参数的宏

                宏函数不是真正的函数,不检查参数类型,没有传参,没有返回值,只有替换后的运算结果

                如何实现:

                1.把代码中使用到宏函数的地方替换为宏函数后面的代码

                2.把宏函数代码中使用的参数替换为调用者提供的参数

            宏的二义性:

                由于宏的位置不同,参数不同导致宏有不同的功能,叫做宏的二义性        #define SUM(A,B)  A*B     sum(num1+10,num2) == num1+10*num2

            如何避免宏的二义性:

                宏函数整体加小括号,每个参数都加上小括号保护

                注意:在使用宏函数时不要提供带自变运算符的变量作为参数

            注意:容易出选择题,直接问哪个有二义性,提供宏函数问宏函数的结果

            注意:宏函数可以用大括号保护代码,定义宏常量,宏函数时不能换行的,但是可以在一行的末尾使用续行符 \  换行

        常考的笔试面试题:

            #define 和  typedef 有什么区别?

            #define 是宏替换

            typedef 是类型重定义

            如果是普通类型时,从功能上没有任何区别

            #define INT int

            typedef int INT

            INT num;

            指针类型有区别:

            #define INTP int*       //p1是指针,p2p3都是int

            INTP p1,p2,p3;          //int* p1,p2,p3;

           

            typedef int* INTP;      //p1 p2 p3都是指针

            INTP p1,p2,p3;          

            2.sizeof和strlen有什么区别?

                sizeof是一个计算变量,类型的字节数的运算符

                strlen是一个计算字符串长度的函数

            3.宏函数与普通函数有什么区别?

                它们是什么?

                    宏函数:是带参数的宏替换,不是真正的函数,只是用起来像函数

                    函数:是一段具有某项功能的代码的集合,会被编译成二进制指令存储在代码段中,函数名就是该段代码的首地址,有独立的栈内存,命名空间

                有什么不同?

                    函数:  返回值        检查参数类型    安全      传参    速度慢      跳转

                    宏函数:运算结果        通用          危险      替换    速度快      

    条件编译:

        根据条件决定让哪些代码参与编译,哪些代码不参与编译

    版本控制:

        #if

        #elif

        #else

        #endif

        注意:还可以使用#if 0   #endif  注释整段代码

    头文件卫士:防止头文件重复包含

        #ifndef 宏名(头文件名大写)

        #define 宏名

        #endif//宏名

    判断,调试:

        #ifdef 宏名

        #else

        #endif

    注意:可以在gcc编译时通过参数 -D宏名 为此次编译的结果添加宏

    调式函数:

    #ifdef DEBUG

        #define debug(...) printf(__VA_ARGS__)

    #else

        #define debug(...)

    #endif

    提示错误报告:

    #define error(...)  printf("%s %s [%d] %s:%m %s %s\n",__FILE__,__func__,__LINE__,__VA_ARGS__,__DATE__,__TIME__)

    作业:

        实现一个交换两个变量的宏函数,能有多少种写法?哪种最通用?

#include <stdio.h>

//#define SWAP(a,b) {a=a+b;b=a-b;a=a-b;}    //可能数据溢出
//#define SWAP1(a,b) {a=a^b,b=a^b;a=a^b;}        //只能整形,ab不能是同一个变量

#define SWAP2(a,b) {long double t=a;a=b;b=t;}    //不能传结构体

#define SWAP3(a,b,type) {type t=a;a=b;b=t;}        //多一个参数

#define SWAP4(a,b) {typeof(a) (t)=(a);(a)=(b);(b)=(t);}        //typeof只能在gnu编译器下用

//#define SWAP3(a,b) int temp = *a;*a = *b;*b = temp    

int main(int argc,const char* argv[])
{
    int num1 = 10,num2 = 20;
    printf ("%d %d\n",num1,num2);
    SWAP3(num1,num2,int);
    printf ("%d %d",num1,num2);
}

#define SWAP(a,b) {typeof(a) (t)=(a);(a)=(b);(b)=(t);}

//typeof只能在gnu编译器下使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值