初出茅庐的小李之C语言必备知识预处理

编译预处理

编译预处理就是在编译源代码之前进行的一系列处理,将源程序中的一些特殊命令进行展开或处理,生成扩展的源代码。这些特殊命令通常以“#”开头,占单独的行,语句尾部不需要加分号。

宏定义

(#define)是一种常见的编译预处理指令,用于定义宏,实现代码的简化和重用。

文件包含(#include)用于在源文件中引入其他文件的内容,方便代码模块化和复用。

条件编译

(#if, #else, #endif等)允许根据条件选择性地编译部分代码,提高代码的灵活性。

在预处理阶段,这些指令会被解释和处理,生成经过预处理的源代码,然后再经过编译、汇编、链接等步骤生成最终的可执行文件。这个过程有助于提高代码的可维护性和可移植性。

书写格式

以“#”开头、占单独行、语句尾不加分号。
这样的规范有助于编译器正确解释和处理这些指令,同时也使得代码更加清晰易读。这样的一致性规范有助于维护代码时的可读性和可理解性。

宏定义的例子

// 定义常量

#include <stdio.h>

#define MAX_SIZE 100
#define PI 3.1415926

// 简化代码
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))


#define DEBUG   //只要定义了该宏 DEBUG_PRINT就会起作用 没有定义则不起作用 

// 字符串拼接

//#define CONCAT_STR(a,b) a##b dev平台用不了 linux未测试
#define CONCAT_STR(a,b) a b

// 条件编译
#ifdef DEBUG
    #define DEBUG_PRINT(msg) printf("Debug: %s\n", msg)
#else
    #define DEBUG_PRINT(msg)
#endif




int main(void) 
{
	
	printf("5的平方是%d\r\n",SQUARE(5));
	printf("MAX(2,3)返回较大的一个数是%d\r\n",MAX(2,3)) ;
	DEBUG_PRINT("调试信息"); 
	printf("%s\r\n", CONCAT_STR("你好", "World"));  // 这里会被展开为 printf("%s\r\n", "你好, " "World");
}

这里踩到了一个坑… dev里这个##符号竟然不能使用!看了这个博主的文章才明白
https://blog.csdn.net/leon1741/article/details/78149881,致谢致敬
在这里插入图片描述

运行结果

在这里插入图片描述

宏定义使用注意事项

使用宏定义时需要注意一些事项,以确保代码的可读性和正确性。以下是一些宏定义的注意事项:

  1. 括号的使用:

    在宏定义中,为了避免优先级问题,通常在宏的参数和整体表达式外部都使用括号。例如:

    #define SQUARE(x) ((x) * (x))
    

    这样可以确保在使用时不会出现预期之外的行为。

  2. 避免副作用:

    在宏中避免使用具有副作用的表达式,因为宏是简单的文本替换,可能导致意外的行为。

    // 避免这样的宏定义
    #define INCREMENT(x) x++
    
  3. 使用大写字母:

    为了与变量和函数名区分,宏的名称通常使用大写字母。

    #define MAX_SIZE 100
    
  4. 多行宏的注意:

    如果宏跨越多行,确保在每行的末尾使用反斜杠 \ 连接,以避免语法错误。

    #define PRINT_SUM(a, b) \
        do { \
            int sum = (a) + (b); \
            printf("Sum: %d\n", sum); \
        } while(0)
    
  5. 参数的使用:

    宏参数的使用要小心,确保在宏展开时不会导致预期之外的结果。

    // 不要这样使用,可能导致问题
    #define SQUARE(x) x * x
    
  6. 条件编译:

    在使用条件编译时,确保相关的宏定义和取消定义都是正确的。

    #ifdef DEBUG
        // ...
    #endif
    

总体来说,清晰、简洁、避免副作用是设计宏定义时的关键原则。良好的宏定义可以提高代码的可读性和可维护性。

在单片机中可以使用预编译来区分代码版本

如果定义了REG_CODE 这个宏且其结果是1那么就是寄存器版本代码否则就是库函数版本代码

void LED_Config(void)
{
	#if (REG_CODE)
	
	RCC->AHB1ENR |= 1<<2;      //GPIOC的时钟开关
  
	GPIOC->MODER &= ~(3<<2*4);//把89位清00 PC4
	GPIOC->MODER |=  (1<<2*4);//只是把第89位置01
	
	GPIOC->MODER &= ~(3<<2*5);//把10 11位清00 PC5
	GPIOC->MODER |=  (1<<2*5);//只是把第89位置01
	
	GPIOC->MODER &= ~(3<<2*6);//把11 12位清00 PC6
	GPIOC->MODER |=  (1<<2*6);//只是把第89位置01
	
	GPIOC->MODER &= ~(3<<2*7);//把89位清00  PC7
	GPIOC->MODER |=  (1<<2*7);//只是把第89位置01
	
	GPIOC->OTYPER &= ~(1<<4); //推挽模式//0xFFFF FFEF 
	GPIOC->OTYPER &= ~(1<<5);
	GPIOC->OTYPER &= ~(1<<6);
	GPIOC->OTYPER &= ~(1<<7);
	
	
	//假设输出状态 灯的开关
	GPIOC->ODR |=  (1<<4)| (1<<5)|(1<<6) |(1<<7);  //默认全关
	printf("寄存器代码...\r\n");
	#else
	printf("LED库函数代码...\r\n");
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	
    GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_OUT;
	GPIO_InitStruct.GPIO_OType  = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd   = GPIO_PuPd_NOPULL;
	GPIO_InitStruct.GPIO_Speed  = GPIO_High_Speed;
	
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	
	#endif
	
}

至此,预编译相关的知识点就介绍完了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/188032.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin学习——流程控制,when,循环,range工具 kt里的equals if实现类似三元表达式的效果

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

张弛声音变现课,惊悚电影配音篇

在提供惊悚片的声音配音服务时&#xff0c;配音员旨在制造一种让观众的心率加快、情绪紧张的气氛。惊悚片侧重于心理层面的紧张和预期的恐怖&#xff0c;声音在塑造这种心理效应中起到了至关重要的作用。演员需通过对声音的精细雕琢和调整来强化电影的悬念和紧迫感。以下是为惊…

C语言SO EASY(ZZULIOJ1220: SO EASY)

题目描述 Superbin最近在研究初等数论&#xff0c;初等数论 是研究数的规律&#xff0c;特别是整数性质的数学分支。它是数论的一个最古老的分支。它以算术方法为主要研究方法&#xff0c;主要内容有整数的整除理论、同余理论、连分数理论和某些特殊不定方程。 是定义在正整数…

2017年2月16日 Go生态洞察:Go 1.8版本的革新

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

rocky8.9配置K8S集群kubernetes,centos同理

rocky8.9配置K8S集群 节点主机名IP地址mastertang1192.168.211.101node1tang2192.168.211.102node2tang3192.168.211.103 1&#xff09;准备工作 全部主机都配置静态ip vi /etc/sysconfig/network-scriptsTYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DE…

华为ensp:单臂路由

通过单臂路由实现vlan之间的互通 将vlan和trunk配置好&#xff0c;我直接就在r1上演示单臂路由 我们要在r1的e0/0/0上面随便配置个ip&#xff0c;如果你不在接口上配置ip那就无法开启协议 R1 interface e0/0/0 进入真实接口随便配置个ip ip add 192.168.10.1 24 再进入子接…

YOLOV7主干改进,使用fasternet轻量化改进主干(完整教程)

1&#xff0c;Pconv&#xff08;来自Fasternet&#xff09;&#xff08;可作为模型中的基础卷积模块使用&#xff09; 论文链接&#xff1a;https://arxiv.org/abs/2303.03667 2&#xff0c;为了大家方便的使用&#xff0c;这里我对原本的PConv的代码做了部分的改动&#xff0…

Executors(线程池操作类)

一&#xff0c;常用方法 二&#xff0c;案例 package XianChengChildren;import java.util.concurrent.*;public class ThewadPoolTest1 {public static void main(String[] args) throws Exception { // ExecutorService pool new ThreadPoolExecutor(3,5,8, // …

C++类与对象(6)—初始化列表、explicit关键字、static成员

目录 一、初始化列表 1、定义 2、注意事项 3、尽量使用初始化列表初始化 4、初始化顺序 二、 explicit关键字 1、定义 三、static成员 1、定义 2、特性 3、例题 一、初始化列表 下面这段代码可以正常编译&#xff1a; class A { private:int _a1;//成员声明int…

企业海外分部,如何实现安全稳定的跨境网络互连?

如今&#xff0c;众多企业广泛采取数字化业务系统&#xff0c;如OA、ERP及CRM等&#xff0c;来提升其业务运营效率。同时&#xff0c;私有云与公有云混合架构也逐渐普及化。 具体来说&#xff0c;很多企业选择将研发系统部署在公司本地的私有云环境&#xff0c;以此确保数据安全…

pgz easyexcel如何给excel文件添加自定义属性

免费API方式 直接上传URL,自定义修改Excel 视频演示【内含接口地址】 https://www.ixigua.com/7304510132812153385 前情提示 | 功能说明 多选仅支持微软office、office365系列Excel。因为WPS宏功能需要企业版且付费生成xlsx、xlsm等文件,office和WPS均可以打开,均可以单…

BTC 复兴:Ordinals 带来创新活力,BitVM 与 BitStream 相继问世

除了备受瞩目的 ETF&#xff0c;今年 Bitcoin 生态迎来全新的发展活力和机遇。Ordinals 协议的横空出世&#xff0c;以此为基础诞生的 BRC20 协议给整个比特币生态带去了一波新的能量&#xff0c;迎来铭文热度高涨。而诸如 BitVM、BitStream 等新技术甫一问世&#xff0c;便引发…

学习分布式事务Seata看这一篇就够了,建议收藏

一、事务的特性 ACID特性 A&#xff08;Atomic&#xff09;&#xff1a;原子性&#xff0c;构成事务的所有操作&#xff0c;要么都执行完成&#xff0c;要么全部不执行&#xff0c;不可能出现部分成功部分失败的情况。 C&#xff08;Consistency&#xff09;&#xff1a;一致…

Python编程技巧 – Lambda函数

Python编程技巧 – Lambda函数 Python Programming Skills – Lambda Functions By JacksonML 2023-11-25 在前文介绍过Python函数&#xff0c;一个函数用def关键字声明&#xff0c;不带或带有参数&#xff0c;并以冒号结束&#xff1b;函数块根据结果由解释器确定返回值动态…

计数问题+约瑟夫问题(map)

目录 一、计数问题 二、约瑟夫问题 一、计数问题 #include<iostream> #include<map> using namespace std; int main() {int n,x;cin>>n>>x;map<int,int>m;for(int i1;i<n;i){if(i>1 && i<10){m[i];}else{int temp i;while (…

MYSQL基础知识之【添加数据,查询数据】

文章目录 前言MySQL 插入数据通过命令提示窗口插入数据使用PHP脚本插入数据 MySQL 查询数据通过命令提示符获取数据使用PHP脚本来获取数据内存释放 后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Mysql &#x1f431;‍&#x1f453;博…

【Jenkins】jenkins发送邮件报错:Not sent to the following valid addresses:

jenkins报错未能发送邮件到指定邮箱 注意&#xff1a;这是在系统配置中修改 在系统配置》邮件通知中添加配置信息 注意&#xff1a;这个是在项目的配置下修改 配置完成后&#xff0c;重新执行发送邮件成功&#xff01;&#xff01;&#xff01;

Python实现一箭穿心

文章目录 &#x1f384;效果&#x1f3f3;️‍&#x1f308;Turtle模块&#x1f339;代码&#x1f33a;代码讲解 &#x1f384;效果 &#x1f3f3;️‍&#x1f308;Turtle模块 Turtle是一个绘图工具&#xff0c;是Python标准库中的一个模块。它提供了一种简单而直观的方式来创…

在JVM中 判定哪些对象是垃圾?

目录 垃圾的条件 1、引用计数法 2、可达性分析 3、强引用 4、软引用 5、弱引用 6、虚引用 判断垃圾的条件 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;垃圾收集器负责管理内存&#xff0c;其中的垃圾收集算法用于确定哪些对象是垃圾&#xff0c;可以被回收…