C语言 宏定义

2023-11-19

一、预备知识
一个项目可以通过 编译链接最终形成一个可执行文件。每个源文件(.cpp)都会单独编译,编译成一个目标文件(.o,也可能是.obj,扩展名跟操作系统有关)。然后系统把这些.o文件进行链接,最终形成一个可执行文件。
编译做的事:词法、语法的分析,目标文件(临时文件).o,.obj的生成,优化之类的,这个编译我们可以拆开来看他干了几个事,一般来讲会干这几件事:
a.预处理;
b.编译:词法、语法分析,目标代码生成,优化,产生一些临时文件。
c.汇编:产生.o/.obj目标文件
预处理:
在源程序.cpp中加入一些特殊的代码(特殊的命令),这些特殊代码有一些特殊的能力,提供一些特殊功能,编译系统会先对这些特殊代码做处理,就叫做“预处理”。处理结果再和源程序代码一起进行上边的 b 的编译,c的汇编这一系列操作。
C语言提供三种预处理功能:
1、宏定义
2、文件包含
3、条件编译
这三种功能也是通过在程序代码中 写代码来实现的,只不过这些代码比较特殊,都是以 #开头
二、不带参数的宏定义
用一个指定的标识符来代表一个字符串;
一般形式
#define  标识符  字符串    //标识符也叫宏名[ 注意:结尾 不需要分号]
#include<stdio.h>
//不带参数的宏定义:用PI来代替3.1415926
#define PI 3.1415926  //程序源码中,我们写的是PI,在编译预处理的时候,所有在该#define之后的PI都会被替换成“3.1415926”
int main()
{
    printf("%f\n",PI);  //相当于替换为printf("%f\n",3.1415926);
    float ftmp;
    ftmp=2*PI;       //相当于替换为ftmp=2*3.1415926;  这种替换不做语法检查,替换完之后直接参与乘法运算
    printf("ftmp=%f\n",ftmp);
}
好处:
A、用一个简单的名字代替一个长字符串,所以这个标识符也被称为宏名,在预编译时将宏名 替换成字符串的过程叫"宏展开",#define 就是宏定义命令。
B、增加了修改的方便性,为修改提供了极大的便利,这种便利被很频繁地使用。也叫提高了程序的可移植性。
说明
(1).宏名(PI)  一般都用大写字母,这是一种习惯,建议都有这样的习惯;
(2) 宏定义 不是C语句,所以不必在行末尾加分号,如果加分号则连分号会被一起替换掉。
(3)  #define 命令出现在程序中函数的外面(一般在.cpp文件最上面,#include下面,函数声明的上面),宏名 的有效范围是 #define 之后,到本源文件结束,不能跨文件使用。
(4) 可以用 #undef 命令终止宏定义命令
(5) 用#define 进行宏定义时,还可以引用已经定义的宏,可以层层置换
(6) 字符串内的字符,即使与宏名相同,是不会进行替换的     
char stmp[20] ="DPICPI";  //这里不会替换成 2*3.1415926 *3.1415926
三、带参数的宏定义
一般形式
#define 宏名(参数表) 字符串             也是用右边 字符串 代替 宏名(参数表)
一般"字符串"中都会包含参数表中所指定的参数,但是不包含也可以,如果不包含,通过参数表传递进去的这个参数干嘛呢,例如:#define S(a,b) a*2 ,那么这里的这个b传递参数进去有什么用呢
#include<stdio.h>
#define S(a,b) a*b  //带参数的宏定义
int main()
{
    int tam=S(2,3);  //把2,3分别代替宏定义中的形式参数 a,b ==> S(2,3)  ==> 2*3
    printf("tam=%d\n",tam);
}
总结:
带参数的宏定义是这样展开置换的:对一般形式中的“字符串”,如果字符串中有 宏名后列出的参数如(a,b),则将程序语句中相应的实参(可以是常量、变量、表达式)代替形参;
如果字符串中的字符不是参数字符,则保留。
#include<stdio.h>
//不带参数的宏定义:用PI来代替3.1415926
#define PI 3.1415926  
#define S(r) PI*r*r
int main()
{
    float area;
    area =S(3.6);  //替换为:3.1415926*3.6*3.6
    printf("圆的面积是:%f\n",area);
    //说明
         //a、如果输入
             area =S(1+5); //表示替换为:3.1415926*1+5*1+5 我们希望的是:3.1415926 * (1+5) * (1+5)
             //可以这样做:在形式参数外面增加一个括号就可以了 ==> #define S(r) PI*(r)*(r)
        //b、宏定义的时候宏名和带参数的括号之间不能有空格,否则空格以后的字符都作为代替字符串的一部分了。
             //#define S (r) PI*r*r S后面不能加空格
}
宏定义和函数的区别
(1) 函数调用时,先求出实参表达式的值,然后带入形参,带参数的宏只进行简单的字符替换;
(2) 函数调用是在程序运行时处理,分配临时内存;而宏展开,是在编译时进行的,展开时是不分配内存,也没有返回值这种说法,也没有值传递这种说法。
(3) 宏的参数没有类型这一说法,只是一个符号,展开时带入到指定字符串中。
(4) 使用宏次数多时,宏展开后源程序变长,函数调用不会使源程序变长;
(5) 宏替换只占用编译时间,不占用运行时间,而函数调用占用的是运行时间(分配内存,传递参数,执行函数体)。
有时候会用宏来替换复杂的语句:
  例如:用来替换比较两个数的大小:  #define MAX(x,y) (x)>(y)?(x):(y) 
       宏替换多行语句: #define MACROTEST do {printf("test\n");} while(0)  也可以这样写
#define MACROTEST do { \      //加上 \ 表示和下面的是一行
printf("test\n"); \
} while(0)
/*宏替换比较两个数的大小*/
#include<stdio.h>
#define MAX(x,y) (x)>(y)?(x):(y)    //这里加上括号以防止出错
int main()
{
    int result=MAX(3,6);   //替换成 (3)>(4)?(4):(4)
    printf("result=%d\n",result);
}
/*宏替换多行语句*/
#include<stdio.h>
#define MACROTEST do { printf("test\n");}while(0)    
int main()
{
    MACROTEST;  //相当于替换为 do { printf("test\n");}while(0)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言 宏定义 的相关文章

  • socket网络编程几大模型?看看CHAT是如何回复的?

    CHAT回复 网络编程中常见的有以下几种模型 1 阻塞I O模型 Blocking I O 传统的同步I O模型 一次只处理一个请求 2 非阻塞I O模型 Non blocking I O 应用程序轮询调用socket相关函数检查请求 不需
  • 让CHAT介绍下V2ray

    CHAT回复 V2Ray是一个网络工具 主要用于科学上网和保护用户的网络安全 它的名字源自Vmess Ray 光线 通过使用新的网络协议 为用户提供稳定且灵活的代理服务 下面是一些V2Ray的主要特性 1 多协议支持 V2Ray 提供了大量
  • 电商数据api拼多多接口获取商品实时数据价格比价api代码演示案例

    拼多多商品详情接口 接口接入入口 它的主要功能是允许卖家从自己的系统中快速获取商品详细信息 通过这个接口 卖家可以提取到商品的各类数据 包括但不限于商品标题 价格 优惠价 收藏数 下单人数 月销售量等 此外 还可以获取到商品的SKU图 详情
  • 用CHAT分析高校体育智慧教学体系构建与探索研究现状

    CHAT回复 现阶段 高校体育智慧教学体系的构建与探索研究还处于初级阶段 但全球数字化转型大潮的推动下 一些较为前沿的研究和实践已经开始出现 1 教学平台的建设 很多高校已经开始尝试使用在线教育平台进行体育教学 把传统的面对面授课模式转变为
  • 软件测试|使用Python读写yaml文件,你会了吗?

    简介 YAML YAML Ain t Markup Language 是一种可读的数据序列化格式 它常用于配置文件和数据交换 Python 提供了许多库来处理 YAML 文件 在本文中 我们将探讨如何使用 PyYAML 库来读取和写入 YA
  • 【计算机毕业设计】二手图书交易系统

    随着世界经济信息化 全球化的到来和互联网的飞速发展 推动了各行业的改革 若想达到安全 快捷的目的 就需要拥有信息化的组织和管理模式 建立一套合理 动态的 交互友好的 高效的二手图书交易系统 当前的信息管理存在工作效率低 工作繁杂等问题 基于
  • 【计算机毕业设计】白优校园社团网站的设计与实现

    近些年 随着中国经济发展 人民的生活质量逐渐提高 对网络的依赖性越来越高 通过网络处理的事务越来越多 随着白优校园社团网站的常态化 如果依然采用传统的管理方式 将会为工作人员带来庞大的工作量 这将是一个巨大考验 需要投入大量人力开展对社团
  • 华为OD机试 Java 【计算文件大小】

    题目 一个电脑文件夹系统 每个文件夹里都有一些文件和可能还有其他子文件夹 给定所有文件夹的大小和子文件夹列表 你的任务是找出某一个文件夹及其所有子文件夹里的文件总大小 输入格式 首行有两个数字 文件夹的总数M和你要查询的文件夹ID N 之后
  • 2024诸多大厂春招提前启动!Android的程序员还在等什么

    春招 提前批 已开 xdm别打瞌睡了 格力 顺丰 酷狗 沃尔玛中国 理想 科大讯飞等开启春招 开始收简历了 还有hc的企业提前抢人 春招时间短 节奏快 招满即止 就算挂了也绝不能不投 对企业来说 秋招和春招都是储备人才的黄金时期 春招中 除
  • 史上最全Java面试八股文(带全部答案)2024年最新版

    今天要谈的主题是关于求职 求职是在每个技术人员的生涯中都要经历多次 对于我们大部分人而言 在进入自己心仪的公司之前少不了准备工作 有一份全面细致 面试题 将帮助我们减少许多麻烦 在跳槽季来临之前 特地做这个系列的文章 一方面帮助自己巩固下基
  • 计算机Java项目|学生成绩管理系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 计算机Java项目|电影购票系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 春眠不觉晓,Java数据类型知多少?基础牢不牢看完本文就有数了

    俺滴座右铭是不在沉默中爆发 就在沉默中灭亡 一起加油学习 珍惜现在来之不易的学习时光吧 等工作之后 你就会发现 想学习真的需要挤时间 厚积薄发啦 我们知道Java是面向对象的静态型编程语言 在Java的世界里万物皆对象 但我认为是万物皆数据
  • 【自适应滤波】一种接近最佳的自适应滤波器,用于突发系统变化研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及文章
  • 【心电图基线估计和去噪方法的群稀疏正则化】带有群稀疏正则化的心电图基线估计和去噪(Matlab实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及文章
  • 用栈实现队列(OJ中报错的处理)

    用栈实现队列 ERROR AddressSanitizer myQueueFree函数中栈的释放处现了问题 没有调用StackDestory而是直接free了 这个是栈初始化时 capacity与malloc申请的空间大小没有匹配 请你仅使
  • 初学者如何快速入门Python(内附详细攻略),一文讲清

    目前python可以说是一门非常火爆的编程语言 应用范围也非常的广泛 工资也挺高 未来发展也极好 Python究竟应该怎么学呢 我自己最初也是从零基础开始学习Python的 给大家分享Python的学习思路和方法 一味的买书看书 看视频 是
  • 2024年华为OD机试真题-分割均衡字符串-Python-OD统一考试(C卷)

    题目描述 均衡串定义 字符串只包含两种字符 且两种字符的个数相同 给定一个均衡字符串 请给出可分割成新的均衡子串的最大个数 约定字符串中只包含大写的 X 和 Y 两种字符 输入描述 均衡串 XXYYXY 字符串的长度 2 10000 给定的
  • 在 Python 中实现 List 抽象

    在 Python 中 创建一个包含多个对象的 list 很常见 例如 对于一组具有相同功能的对象 比如播放声音 希望能够使用类似 my list play 的语法来触发 list 中所有对象的 play 方法 另一个例子是 当希望关闭 li
  • Java开发中不要使用受检异常

    简介 Java是唯一 主流 实现了受检异常概念的编程语言 一开始 受检异常就是争议的焦点 在当时被视为一种创新概念 Java于1996年推出 如今却被视不良实践 本文要讨论Java中非受检异常和受检异常的动机以及它们优缺点 与大多数关注这个

随机推荐

  • 【pyqt5学习】——菜单栏(QMenu())、工具栏QToolBar学习

    目录 1 菜单栏 QMenu 一般在窗口顶部 1 创建菜单栏步骤 2 信号与方法 3 实操 2 工具栏 一般在菜单栏下方 1 创建步骤 2 方法与信号 信号 方法 3 实操示例 3 状态栏QStateBar 用于显示状态信息 一般在窗口底部
  • 微信开放平台接入问题

    1 errcode 40163 errmsg code been used rid xxxxx 原因 获取token时 使用的code码被二次使用 2 errcode 40249 errmsg this template msg has b
  • python中的unicode

    Python s Unicode string type stores characters from the Unicode character set In this set each distinct character has it
  • 怎么样不使用python做到图片爬虫呢?试试这个神奇软件吧

    1 首先在 主题 选项 选择你需要搜索的内容 2 填写需要下载的文件数量 这个需要留意 如果没有更改保存地址 那么会覆盖以前的文件 3 任意选择一个你想保存的地址 链接 https pan baidu com s 16yKPdUEC355j
  • Eureka迁移到Nacos之服务名称大小问题解决

    我们应用往Eureka中注册使用的名称以及应用内部通过Feign调用 使用的服务名称都是小写 如user service 但是注册到Eureka中后 应用的名称全部都是以大写的形式存储及展现 由于Eureka客户端对大小写的支持都是一样的
  • 前端工程化:模块化、包管理工具、打包工具(Webpack基本使用和优化)、前端性能监控

    目录 1 模块化 1 CommonJS AMD CMD 1 1 背景 1 2 CommonJS规范的核心变量 1 3 exports module exports 和require本质 1 4 exports和module exports的
  • 为什么有些Buck-Boost芯片没有输出负压?

    大家好 这里是大话硬件 今天分享一篇和Buck Boost拓扑相关的问题 也是在最开始接触Buck Boost芯片时 就在内心产生了疑问 在开始学习DC DC拓扑时 很多资料都说 非隔离型的DC DC拓扑常见的有3种 分别是Buck Boo
  • 破解sqlyog 30天试用限制

    安装sqlyog后 进入注册表编辑器 进入 HEYK CURRENT USER Software 找到以 括起来的那项 最新10 XX版本的是 8E919370 318F 4E5E 9EbE 9147B1DB66C9 不用去关注里面的值 右
  • ‘Web\xxx\node_modules\.bin\‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。internal/modules/cjs/loader.js:905throw err

    运行 npm run serve 报上面的错误 错误原因 文件夹名称中不能有
  • Python matplotlib作图时,设置横纵坐标轴数值以百分比(%)显示

    一 当我们用Python matplot时作图时 一些数据需要以百分比显示 以更方便地对比模型的性能提升百分比 二 借助matplotlib ticker FuncFormatter 将坐标轴格式化 例子 encoding utf 8 im
  • C语言:整型在内存中的存储及表示形式(附习题)

    我们都知道 一个变量的创建是要在内存中开辟空间的 而空间的大小是根据不同的类型而决定的 那么数据在开辟空间中是如何存储的呢 首先我们先了解以下概念 一 整数的表示形式 原码 反码 补码 计算机中的整数有三种表示方法 即原码 反码和补码 三种
  • Unity 使用LineRenderer连接2个物体

    1 在Hierarchy面板中创建2个GameObject A和B 这就是希望连接的2个物体 2 同理创建1个EmptyObject C 挂上LineRenderer组件 记得给Materials赋值 3 创建1个新的C 脚本LineMan
  • jenkins解决不能打印springboot启动日志问题

    背景 已经可以在jenkins打包部署 但不能显示springboot启动日志 导致springboot启动报错时 并不知道具体原因 还需要登录linux系统去查看原因 主要步骤 1 开启远程服务器日志 2 利用sed命令 结束tail命令
  • String类

    下面是关于String类1相关的知识点 关于Java JDK 中内置的一个类 java lang String 1 String表示字符串类型 属于引用数据类型 不属于基本数据类型 2 在java 中随便使用双引号括起来的都是String对
  • 计算机领域中随处可见的抽象

    想要管理多种具体的东西 那么需要遵守每种东西的规范 如果想要提供一种通用模式来对这些具体的东西统一管理 需要使用一种古老的技术 抽象 抽象是将多种具体的东西 管理时需要遵守的规范 的共同点抽取出来 放入到更高一层的抽象层 在抽象层不定义或少
  • unix环境高级编程——文件IO

    本期主题 unix环境高级编程 文件IO 文件IO 0 引言 1 文件描述符 2 IO编程中常用的API接口 1 open函数 2 close函数 3 read函数 4 write函数 5 lseek函数 3 函数sync fsync和fd
  • 51单片机中断详解(上)

    一 中断的概念 中断发生 CPU在处理某一事件A时 发生了另一事件B请求CPU迅速去处理 中断响应和中断服务 CPU暂时中断当前的工作 转去处理事件B 中断返回 待CPU将事件B处理完毕后 再回到原来事件A被中断的地方继续处理事件A 这一过
  • pgpool-II常见错误

    持续更新中 1 pg hba中的项不匹配 假设您的pgpool集群中有2个节点 您更新了其中一个节点中的pg hba conf条目 但忘记在其他节点上应用相同的条目 您会看到如下错误 psql d postgres U postgres h
  • 在Linux下编译micropython源码的方法(包括win10的ubuntu子系统)

    本文介绍了在Linux下编译micropython源码的方法 包括了虚拟机 win10子系统等 在Win10的应用商店中 提供了Linux的子系统 这是实际上是一个虚拟机软件 与virtualbox和vmplayer功能类似 下面就介绍在L
  • C语言 宏定义

    一 预备知识 一个项目可以通过 编译 链接最终形成一个可执行文件 每个源文件 cpp 都会单独编译 编译成一个目标文件 o 也可能是 obj 扩展名跟操作系统有关 然后系统把这些 o文件进行链接 最终形成一个可执行文件 编译做的事 词法 语