8月22日笔记C语言基础(补3)宏定义与条件编译2

本文详细介绍了C语言的预处理过程,包括宏定义、头文件包含、条件编译等概念,并展示了如何使用宏进行无参和带参的宏定义,以及如何解决带参宏的问题。条件编译用于根据不同的条件选择性编译代码段,常用于调试和平台适配。此外,文章还给出了一个实例,展示了如何使用宏解析嵌入式设备传输的数据包中的温度、湿度、门状态和灯状态。
摘要由CSDN通过智能技术生成

1.预处理
    程序在编译之前,是由预处理器CC1先检查c文件有没有以#号开头的符号称为宏
    如果有,CC1是不会做任何的逻辑判断直接将里里面的内容替换出来,或者拷贝出来
    我们把这种方式称为宏展开
    
预处理指令(宏)包括
    1.头文件 #include 
    2.定义宏 #define
    3.取消 #undef
    4.条件编译 #if #ifdef #ifndef #else #elif #endif
    5.向编译器发送指令 #pragma
        #pragma pack(1) // 设置结构体M值的大小
        加载库
        


2.宏的概念
    宏其实就是一段特定的字符串,在预处理的时候会被替换
    
3.宏的分类
    1.无参宏之自定义宏
        无参宏的意思是使用的时候无需指定任何的参数
    例如: 
        #define PI 3.14
        #define LCD_SIZE 800*480*4
        
    注意:此处的PI表示宏,一般使用大写字母表示,用于区分变量和函数,当然这不是
        语法规定,只是个人习惯而已
        
    2.无参宏之系统宏
        #define O_RDONLY : 0x1 
        #define O_WRONLY : 0X2
        #define NULL ((void *)0) char *p = NULL 等价于 char *p = (void *)0;
        
    3.带参宏
        带参宏意味着宏定义是可以带参数的,从形式上看是和函数很像
        
        #define MAX(a,b) a>b ? a : b 
        #define MIN(a,b) a<b ? a : b 
        
    4.带参数的宏的特点:
        1.直接文本替换,不做任何的语法判断,不做任何的中间转换
        2.宏在预编译的时候已经被替换了,所以运行的时候不存在宏
        3.宏展开的时候浪费了内存空间,但是节约了程序运行的时间
        
    5.带参宏的问题解决方式:
        //#define MAX(a,b) a>b ? a : b // 容易出bug 解决方法如下
        #define MAX(a,b) ((a)>(b) ? (a) : (b))
    
    6.无值的宏
        #define _MYHEAD_H
        #define WIN_32
        #define WIN_64
        
        无值宏一般是头文件或者在编译中作为判断条件出现
        
    7.总结
        1.宏是用于替换指定的表达式,增加代码的可读性
        2.使得程序修改比较方便,如果程序有多个地方使用到宏的时候,只需要修改宏定义即可
        3.提高程序的运行效率


2.条件编译
    是用来控制编译器编译哪一段代码
    #if                如果条件为真,则执行相应的操作,可以起到类似于注释的效果
    #elif             如果前面的为假,那么执行此语句
    #else           如果前面的操作都为假,则执行以下语句
    #endif          结束条件编译
    #ifdef           如果改宏已经被定义则执行相应的操作
    #ifndef         如果宏没被定义,则执行相应的操作
    
    #if -- #else -- #endif
    格式如下:
    #if 条件表达式
        代码段1
    #else
        代码段2
    #endif
    demo:

       #define DEBUG 1

        int main()
        {
            #if 0 // 0 为假
                printf("此处为假\n");
            #else
                printf("此处为真\n");
            #endif
            
            #if DEBUG //DEBUG 为真
                printf("此处为真\n");
            #else
                printf("此处为假\n");
            #endif // 结束
            return 0;
        }


  条件编译,多路分支
    #if -- #elif -- #elif -- #endif
    #define A 1
    #define B 2
    #define C 3
    //-----------------
    #if A
        printf("A\n");
    #elif B
        printf("A\n");
    #elif C
        printf("A\n");
    #endif    
  


    检测程序中如果没有定义宏则定义
    #ifndef --- #define --- #endif
    定义格式
        #ifndef 标识符
        #define 标识符 替换列表
        #endif
    demo:

        #define PI 3.1415
        #ifndef PI
        #define PI 3.14
        #endif

   运用场景主要是头文件


    检测如果定义了宏则删除
    #ifdef -- #undef -- #endif
    定义格式:
        #ifdef 标识符
            代码段1
        #endif
    demo:

        #define N 456
        #ifdef N
        #undef N
        #define N 123
        #endif


   条件编译的使用场景
    在程序中,用条件编译将调试语句包裹起来,通过gcc编译器来选择编译哪一段
    代码
    int main()
    {
        #ifdef A // 现在没有定义此宏
            printf("A\n");
        #else
            printf("haha\n");
        #endif
        
    }
    编译方法:
        gcc main.c -o main -DA // -D 的意思是编译程序的时候定义哪一个宏
        
作业:

    现有一个嵌入式设备终端传输过来的数据包是一个32位无符号的整型数,这个数据包里面各位含义如下:
    00-07位:表示温度数据
    08-15位:表示湿度数据
    16-19位:表示4扇门状态(门的编号0-3)      二进制:0001  0010 0100 1000   十六进制 1 2 4 8
    20-23位:表示四盏灯的状态(灯编号0-3)
    24-31位:预留备用
    下面是最近一段时间接受的数据包:
    0x12344520, 0xff004B1C,0x00553C1E
    请编写一个程序接收这3个数据包,并解析出对应的数据【温度,湿度,门0-3,灯0-3】(门和灯的状态0-关,1-开)。
    
    使用宏来实现以上功能:
    提示

    #define TEMP_MASK 0x000000FF
    #define HUMI_MASK 0x0000FF00
    

    #include <stdio.h>
    #define TEMP_MASK 0x000000FF
    #define HUMI_MASK 0x0000FF00
    
    #define TEMPERATURE(a) ((a&TEMP_MASK) >> 0)
    #define HUMIDITY(a)  ((a&HUMI_MASK) >> 8)
        
    #define DOOR0_MASK 0x00010000
    #define DOOR1_MASK 0x00020000
    #define DOOR2_MASK 0x00040000
    #define DOOR3_MASK 0x00080000
    
    #define LIGHT0_MASK 0x00100000
    #define LIGHT1_MASK 0x00200000
    #define LIGHT2_MASK 0x00400000
    #define LIGHT3_MASK 0x00800000
    
    int main()
    {
        unsigned int data;
        printf("请输入接收到的数据:\n");
        while(1)
        {
            scanf("%x",data);
            
            printf("温度:  %d\n",TEMPERATURE(data));
            printf("湿度:  %d\n",TEMPERATURE(HUMIDITY));
            
            printf("门0: %s\t",(data & DOOR0_MASK) ? "开":"关");
            printf("门1: %s\t",(data & DOOR1_MASK) ? "开":"关");
            printf("门2: %s\t",(data & DOOR2_MASK) ? "开":"关");
            printf("门3: %s\t",(data & DOOR3_MASK) ? "开":"关");
            
            printf("灯0: %s\t",(data & LIGHT0_MASK) ? "亮":"灭");
            printf("灯1: %s\t",(data & LIGHT1_MASK) ? "亮":"灭");
            printf("灯2: %s\t",(data & LIGHT2_MASK) ? "亮":"灭");
            printf("灯3: %s\t",(data & LIGHT3_MASK) ? "亮":"灭");
            
        }
        
    }


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值