C语言:define定义常量和定义宏(详解)

本篇博客给大家带来的是#define定义常量和#define定义宏的方法

🐟🐟文章专栏:C语言

🚀🚀若有问题评论区下讨论,我会及时回答

❤❤欢迎大家点赞、收藏、分享

你们的支持就是我创造的动力

今日思想:本来就一无所有,何必瞻前顾后呢!


 1、预定义符号

int main()
{printf("%s\n", __FILE__);//打印当前编译的源文件printf("%d\n", __LINE__);//代码的行号printf("%s\n", __DATE__);//文件编译的日期printf("%s\n", __TIME__);//文件被编译的时间printf("%d", __STDC__);//如果编译器遵循ANSIC则值为1,否则未定义return 0;
}

上面是C语⾔设置了⼀些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。

 2、define定义常量

基本语法:

#define 名字  常量

例如: 

#define M  10

 变态代码1:

#define forever for(;;);

这个代码一旦被使用,永远不会执行下面的代码

 变态代码2:

#define PRINT printf("the val of \
is %d\n",n);

注释:\是续行符。

上面的代码相当于:

 printf("the val of is %d\n",n);

 变态代码3:

#define CASE break;case

这个代码意思是:在写case语句的时候自动把break语句写上。

3、define定义宏

宏的基本语法:

#define name(parament-list) stuff

注意:参数列表的左括号必须与name紧邻,如果两者之间有任何空⽩存在,参数列表就会被解释为stuff的 ⼀部分。

代码实例: 

#define	DEV(n) n*nint main()
{int n = 10;int a = 4;printf("%d\n", DEV(n));printf("%d\n", DEV(a));return 0;
}

提示:#define DEV(n) n*n在预处理时会把使用DEV(n)的代码替换成n*n,上面代码替换之后会变成

这样: 

#define	DEV(n) n*nint main()
{int n = 10;int a = 4;printf("%d\n", n*n);printf("%d\n", a*a);return 0;
}

 特殊情况:

#define	DEV(n) n*nint main()
{int n = 10;int a = 4;printf("%d\n", DEV(n+1));printf("%d\n", DEV(a+1));return 0;
}

替换之后:

#define	DEV(n) n*nint main()
{int n = 10;int a = 4;printf("%d\n", n+1*n+1);printf("%d\n", a+1*a+1);return 0;
}

得出的结果和想象的不一样

所以要在宏的参数部分加上括号,即:

#define	DEV(n) ((n)*(n))int main()
{int n = 10;int a = 4;printf("%d\n", DEV(n+1));printf("%d\n", DEV(a+1));return 0;
}

注意:用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。

 4、宏和函数的对比

函数实现加法:

//完成两个数的相加
int Add(int x, int y)
{return x + y;
}
int main()
{int n = 10;int a = 4;printf("%d\n", Add(n,a));//printf("%d\n", DEV(a));return 0

 宏实现加法:

#define	ADD(x,y) x+y
//完成两个数的相加int main()
{int n = 10;int a = 4;printf("%d\n", ADD(n,a));//printf("%d\n", DEV(a));return 0;
}

这两个方式都能实现加法,但是哪个更好呢???

使用宏的方式实现更好

原因如下:

1. 用于调⽤函数和从函数返回的代码可能比实际执行这个小型计算⼯作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜⼀筹。

2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适⽤于整形、⻓整型、浮点型等可以用于 > 来比较的类型。宏的参数是类型无关的。

和函数相比宏的劣势: 

1. 每次使用宏的时候,⼀份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序 的长度。

2. 宏是没法调试的。

3. 宏由于类型无关,也就不够严谨。

4. 宏可能会带来运算符优先级的问题,导致程容易出现错。

 5、#和##号运算符

        5.1、#号运算符

        #运算符将宏的⼀个参数转换为字符串字面量。它仅允许出现在带参数的宏的替换列表中。 #运算符所执行的操作可以理解为”字符串化“。  

代码示例:假如我们想打印the value of  a is 10


#define PRINT(n) printf("the value of "#n " is %d", n);
int main()
{int a=10;PRINT(a);return 0;
}

预处理替换之后:


#define PRINT(n) printf("the value of "#n " is %d", n);
int main()
{int a=10;printf("the value of "a " is %d", n);return 0;
}

        5.2、## 运算符

        ## 可以把位于它两边的符号合成⼀个符号,它允许宏定义从分离的文本片段创建标识符。 ## 被称为记号粘合 

 代码实例:

函数实现:

int int_max(int x, int y)
{return x > y ? x : y;
}

宏的实现方式:

#define GENERIC_MAX(type) \
type type##_max(type x, type y)\
{ \return (x>y?x:y); \
}

这两个代码一模一样

6、程序员的好习惯

宏的名字全部大小

函数名部分大写 

7、undef 

undef:用于移除一个宏定义 

代码实例:

int main()
{int n = 10;int a = 4;printf("%d\n", ADD(n,a));//printf("%d\n", DEV(a));
#undef ADD(x,y) x+yprintf("%d\n", ADD(n, a));//会报错return 0;
}

 8、条件编译

    调试性的代码,删除可惜,保留⼜碍事,所以我们可以选择性的编译。  

     代码实例:

#define M 10
int main()
{#ifdef MAX//如果定义了M则打印haha,这句代码相当于#if define(MAX)printf("haha\n");#endif//注意:#ifdef和#endif配套使用,#endif我的理解是结束if语句#ifndef M//如果没有定义M就打印hei hei,相当于#if !define(M)printf("hei hei\n");#endif // !M//如果没有定义M就打印hei heireturn 0;
}

注意:这样的语句在预编译的时候会选择编译,上面的代码相当于:

#define M 10
int main()
{printf("haha\n");return 0;
}

还有这样的代码:

int main()
{int x = 10;int y = 20;
#if(x>y)printf("%d", x);
#elif(x==y)//相当于else ifprintf("%d", y);
#elseprintf("%d", y);
#endifreturn 0;
}

选择编译后:

int main()
{int x = 10;int y = 20;printf("%d", y);return 0;
}

9、头文件的包含

        自己写的头文件用"",例如#include"name,h"

        库里面的头文件用<>,例如#include<stdio.h> 

自己写的头文件的查找文件:先在源文件所在⽬录下查找,如果该头文件未找到,编译器就像查找库函数头文件⼀样在标准位置查找头文件。 如果找不到就提示编译错误

库头文件的包含的查找方式:直接去标准路径下去查找,如果找不到就提示编译错误。

注意:其实库文件的包含也可以用"",但是比较费时间 

如果包含连续包含一模一样的头文件会耗费代码运行的时间,我们可以这样做来防止这样的事例发生:

 #pragma once

或者

#ifndef ___TEST_H__
#define<test.h>
#end

 完!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot如何实现防盗链

一、什么是盗链 盗链是个什么操作&#xff0c;看一下百度给出的解释&#xff1a;盗链是指服务提供商自己不提供服务的内容&#xff0c;通过技术手段绕过其它有利益的最终用户界面&#xff08;如广告&#xff09;&#xff0c;直接在自己的网站上向最终用户提供其它服务提供商的…

Unity入门(了解生命周期)

目录 1.新建Script&#xff08;给物体添加C#代码&#xff09; 2.Unity常用的生命周期介绍 1.新建Script&#xff08;给物体添加C#代码&#xff09; 首先点击物体&#xff0c;选择Add Component 搜索 New Script&#xff0c;自命名添加这里命名为PlayerController 2.打开Pla…

【OpenCV】图像阈值

简单阈值法 此方法是直截了当的。如果像素值大于阈值&#xff0c;则会被赋为一个值&#xff08;可能为白色&#xff09;&#xff0c;否则会赋为另一个值&#xff08;可能为黑色&#xff09;。使用的函数是 cv.threshold。第一个参数是源图像&#xff0c;它应该是灰度图像。第二…

神经网络中的过拟合问题及其解决方案

目录 ​编辑 过拟合的定义与影响 过拟合的成因 1. 模型复杂度过高 2. 训练数据不足 3. 训练时间过长 4. 数据特征过多 解决方案 1. 数据增强 2. 正则化 3. Dropout 4. 提前停止 5. 减少模型复杂度 6. 集成学习 7. 交叉验证 8. 增加数据量 9. 特征选择 10. 使…

Redis篇-4--原理篇3--Redis发布/订阅(Pub/Sub)

1、概述 Redis 发布/订阅&#xff08;Publish/Subscribe&#xff0c;简称 Pub/Sub&#xff09;是一种消息传递模式&#xff0c;允许客户端订阅一个或多个通道&#xff08;channel&#xff09;&#xff0c;并接收其他客户端发布到这些通道的消息。 2、Redis 发布/订阅的主要概…

ubuntu 7z解压rar文件报错:unsupported method message

问题说明 最近项目需要支持线上上传rar格式&#xff0c;7z来解压缩入库。开发测试过程中发现使用以下命令解压报错&#xff0c; 7z x FileImportTest01.rar -p"123456" -o/home/download -y文件目录内容已列出&#xff0c;但无法解压文件!!! 仔细检查命令没有问题…

流网络等价性证明:边分解后的最大流保持不变

流网络等价性证明:边分解后的最大流保持不变 问题描述证明思路伪代码C 代码实现解释问题描述 在流网络中,证明将一条边分解为两条边所得到的是一个等价的网络。具体来说,假设流网络 $ G $ 包含边 $ (u, v) $,我们以如下方式创建一个新的流网络 $ G’ $: 创建一个新结点 $…

编译问题 fatal error: rpc/rpc.h: No such file or directory

在编译一些第三方软件的时候&#xff0c;会经常遇到一些文件识别不到的问题&#xff0c;这里整理下做个归总。 目前可能的原因有&#xff08;排序分先后&#xff09;&#xff1a; 文件不存在&#xff1b;文件存在但路径识别不了&#xff1b;…… 这次以常见的编译lmbench测试…

小皮面板(PHPSTUDY)配置多个域名或IP

问题描述 小皮面板默认采用nginx的静态部署&#xff0c;按照使用nginx的习惯只需要额外添加一个server即可&#xff0c;但是会发现直接往配置文件里添加新的server是不生效的&#xff0c;小皮的官网论坛几乎已经停止维护&#xff0c;因此资料较少&#xff0c;原本也没有仔细使…

《AI行政管理:开启高效治理新时代》

一、引言 AI 行政管理能力的定义和重要性 AI 行政管理能力是指人工智能在行政管理领域的应用能力。它涵盖了多个方面&#xff0c;包括政府决策支持、公共服务优化、行政流程自动化、社会治理与公共安全以及政府内部管理等。在当今时代&#xff0c;AI 行政管理能力具有至关重要…

Golang使用etcd构建分布式锁案例

在本教程中&#xff0c;我们将学习如何使用Go和etcd构建分布式锁系统。分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要。它有助于维护一致性&#xff0c;防止竞争条件&#xff0c;并确保在任何给定时间只有一个进程独占访问资源。 我们将使用Go作为编程语言&am…

数字IC后端实现常见的physical only cell都有哪些?如何添加这些cell?

数字IC后端实现阶段常见功能cell有哪些&#xff1f;比如AND&#xff0c;AOI&#xff0c;NAND等。 physical cell有哪些&#xff1f;都是干什么用的&#xff1f; 数字后端零基础入门系列 | Innovus零基础LAB学习Day9 &#xff08;1&#xff09; well tap cells&#xff1a;防止…

【NVIDIA orin nx 安装ultralytics yolov11】

注意:不同用户安装的python可能会在不同的路径,因此不同的pip管理会导致安装的 torch和torchvision会在不同的路径下 记得区分用户来运行yolo 一、确认系统 JetPack 版本 此处使用5.1.1 1、查看JetPack 版本 jtop二、安装 ultralytics、pytorch、torchvision、onnxruntime…

CANDENCE:过孔设置 及 如何放置过孔

过孔设置 1、 2、 3、弹出如下对话框 4、选择需要的过孔尺寸&#xff0c;双击 5、调节过孔优先级 6、点击 ”OK“ 完成设置 放置过孔 及 过孔选择 在PCB设计窗口 切换到走线模式 走线时&#xff0c;侧边栏可以选择过孔尺寸 选择好后&#xff0c; 双击左键放置过孔 也…

React 和 Vue _使用区别

目录 一、框架介绍 1.Vue 2.React ?二、框架结构 1.创建应用 2.框架结构 三、使用区别 1.单页面组成 2.样式 3.显示响应式数据 4.响应式html标签属性 5.控制元素显隐 6.条件渲染 7.渲染列表 react和vue是目前前端比较流行的两大框架&#xff0c;前端程序员应该将…

基于多视角深度学习技术的乳腺X线分类:图神经网络与Transformer架构的研究|文献速递-生成式模型与transformer在医学影像中的应用速递

Title 题目 Mammography classification with multi-view deep learning techniques:Investigating graph and transformer-based architectures 基于多视角深度学习技术的乳腺X线分类&#xff1a;图神经网络与Transformer架构的研究 01 文献速递介绍 乳腺X线检查是乳腺癌…

SQL项目实战与综合应用——项目设计与需求分析

项目设计与需求分析是软件开发过程中的核心环节&#xff0c;尤其在涉及数据库的应用时&#xff0c;良好的设计将直接影响到项目的可扩展性、性能和维护性。本文将深入探讨数据库设计的最佳实践&#xff0c;结合 C 与 SQL 的实际应用场景&#xff0c;涵盖项目需求收集、数据库设…

【HarmonyOS学习日志(13)】计算机网络之TCP/IP协议族(二)

文章目录 TCP/IP协议族ARPDNS标志字段&#xff1a;协商具体的通信方式和反馈通信状态DNS查询问题的格式资源记录&#xff08;Resource Record, RR&#xff09;格式&#xff1a;被用于应答字段、授权字段和额外信息字段 IP协议IP服务的特点无状态无连接不可靠 IP头部结构IPv4头部…

GO并发编程

一、并发编程初体验和问题 关于 Go 语言和线程的关系 Go 语言中存在线程。Go 语言的并发模型是基于 Goroutine、Processor&#xff08;P&#xff09;和 Machine&#xff08;M&#xff0c;操作系统线程&#xff09;的 GMP 模型。Goroutine 是 Go 语言中轻量级的执行单元&#xf…

初次使用uniapp编译到微信小程序编辑器页面空白,真机预览有内容

uniapp微信小程序页面结构 首页页面代码 微信小程序模拟器 模拟器页面为空白时查了下&#xff0c;有几个说是“Hbuilder编译的时候应该编译出来一个app.js文件 但是却编译出了App.js”&#xff0c;但是我的小程序结构没问题&#xff0c;并且真机预览没有问题 真机调试 根据defi…