C语言 学习笔记 2021年11月24日

本文详细介绍了C语言中的预处理指令,包括文件包含、宏定义、条件编译等。预处理是在真正编译之前进行的,用于转换代码的阶段。讲解了#include的两种形式,以及如何通过-I指定查找路径。宏定义分为宏常量和宏函数,强调了宏定义的注意事项和可能的二义性问题。还提到了如何通过条件编译实现版本控制和头文件卫士,以防止重复包含。此外,文章还讨论了宏函数与普通函数的区别,并给出了相关的笔试面试题和示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

预处理指令:
    程序员所编写的代码并不能被真正的编译器编译,需要一段程序把代码翻译一下
    翻译的过程叫预处理,负责翻译的程序叫做预处理器,被翻译的代码叫做预处理指令,以#开头的代码都是预处理指令

    查看预处理过程
        gcc -E code.c   把预处理的结果显示到终端上
        gcc -E code.c -o code.i 把预处理结果存储到code.i预处理文件中

    预处理指令的分类:
        #include 文件包含
            #include <> 从系统指定路径查找并导入头文件
            #include "" 从当前路径查找,如果找不到再从系统指定路径查找并导入头文件
            通过编译参数指定查找路径 -I /path
            操作系统通过设置环境变量来指定头文件的查找路径

        #define 定义宏
            宏常量:    #define 宏名 数据
                #define MAX 50
                优点:提高代码可读性、提高可扩展性(方便批量修改)、提高安全性、还可以用在case后面

                注意:一般宏名全部大写,末尾不要加分号

                预定义的宏:
                    __func__    获取函数名
                    __FILE__    获取文件名
                    __DATE__    获取当前日期
                    __TIME__    获取当前时间
                    __LINE__    获取当前行号

            宏函数:  带参数的宏
                不是真正的函数,不检查参数的类型,没有传参,只是值替换,没有返回值,只有表达式的计算结果
                #define SUM(a,b,c) ((a)+(b)+(c)) 
                1、把代码替换为宏函数后面的表达式代码
                2、把宏函数代码中使用的参数替换为调用者提供的数据

                注意:定义宏常量、宏函数不能直接换行,可以使用续航符 \ 放在末尾可以换行
                    也可以使用大括号保护代码

            宏函数的二义性
                由于宏函数所处的位置、参数不同导致宏函数有不同的解释和功能,这种叫做宏的二义性

                如何避免二义性:
                    1、宏函数整体代码加小括号
                    2、每个参数都加小括号
                    3、使用宏函数时不要提供带自变运算符的变量作为参数
                注意:容易出选择题,例如:哪个宏有二义性、选择出宏函数的结果
                注意:宏函数可以使用大括号保护代码,定义宏常量、宏函数是不能换行,但是可以在一行的末尾使用续行符\换行
    常考的笔试面试题:(C语言中与指针相关的知识点有哪些)
        如果是普通类型,它们的功能上没有区别
        #define INI int
        typedef int INT;
        如果是指针类型
        #define INIP int*
        INTP p1,p2,p3; //p1是指针,p2p3是int类型变量
        typedef int* INTP;
        INTP p1,p2,p3; //p1p2p3是指针

        宏函数与普通函数的区别?
            是什么?
            宏函数:不是真正的函数,只是代码的替换,用起来像函数
            函数:一段具有某项功能的代码,会被编译成二进制指令存储在代码段中,函数名就是它的首地址,有独立的命名空间、栈空间
            有什么不一样?
            函数:    返回值     类型检查   安全 入栈、出栈     速度慢 跳转
            宏函数:运行结果  通用          危险 替换                速度快 冗余

    条件编译:
        根据条件决定让代码是否参与最终的编译

        版本控制:
            #if
            #elif
            #else
            #endif

        头文件卫士:防止头文件重复包含
            #ifndef  宏名(头文件名全大写,_替代.)        #ifndef  HEAD_H
            #define  宏名(头文件名全大写,_替代.)       #define  HEAD_H
            #endif //宏名(头文件名全大写,_替代.)        #endif//HEAD_H

        判断、调试代码:
            #ifdef  宏名(DEBUG)
            #else
            #endif
            注意:可以通过编译参数-D宏名 定义宏

        封装调试函数
        #ifdef DEBUG
            #define debug(...) printf(__VA_ARGS__);     //...是可变长参数
        #else
            #define debug(...)
        #endif

        封装提示错误信息宏函数
        #define error(...) fprintf(stdout,"%s %s %s %m %d %s %s",__FILE__,__func__,__VA_ARGS__,__LINE__,__DATE__,__TIME__);
        #define error(...) printf("%s %s %s %m %d %s %s",__FILE__,__func__,__VA_ARGS__,__LINE__,__DATE__,__TIME__);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值