预处理详解(一)

目录

  • 预定义符号
  • define定义常量
  • define定义宏
  • 宏替换的规则
  • 宏与函数的对比

预定义符号

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

__FILE__ //进⾏编译的源⽂件
__LINE__ //⽂件当前的⾏号
__DATE__ //⽂件被编译的⽇期
__TIME__ //⽂件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义

举个例子:

printf("file:%s line:%d\n", __FILE__, __LINE__);

在这里插入图片描述

define定义常量

基本语法:

#define name stuff

举例:

#define MAX 1000
#define reg register //为 register这个关键字,创建⼀个简短的名字
#define CASE break;case //在写case语句的时候⾃动把 break写上。
// 如果定义的 stuff过⻓,可以分成⼏⾏写,除了最后⼀⾏外,每⾏的后⾯都加⼀个反斜杠(续⾏符)。
#define DEBUG_PRINT printf("file:%s\tline:%d\t \date:%s\ttime:%s\n" ,\__FILE__,__LINE__ , \__DATE__,__TIME__ ) 

思考一下#define后面要加一个“;”吗?

#define M 100;

建议是不要加,因为在一些情况下可能会出现报错。

#define M 100;
int main()
{int a = 0;scanf("%d", &a);if (a)a = M;elsea = 0;return 0;
}

在这里插入图片描述
因为预编译时他会把M替换成“100;”,这样在预编译时if语句就会变成:

if(a)
a=100;;

这样if在没有{}的情况下后面跟了一个语句和一个空语句就会报错。

define定义宏

#define机制包括了⼀个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
定义宏的方法:

#define name( parament-list ) stuff

其中parament-list是一个参数,可以替换到文本stuff中。
例如:

#define ADD(X) (x)+(x)

用define定义一个用来加法的宏。
但是我们在定义宏时不要吝啬“()”,否则也会出现一些问题,比如:

#define MUL(x) x*x
int main()
{
int ret = MUL(5+1) ;
//与编译后他会变成:
//int ret = 5+1*5+1;
return 0;
}

所以我们在定义宏时要考虑一些因素,比如相邻操作符的优先级与相互影响。
同时我们在使用宏定义时也要避免一些特别参数的传参,比如“x++”:

#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
...
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);//输出的结果是什么?

在这里插入图片描述
参数写为x++时,会在宏的使用过程中,改变x的值,导致我们宏的预期结果与想象的略有偏差。

宏替换的规则

在程序中扩展#define定义符号和宏时,需要涉及几个步骤。

  1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
    也就是如下类型先替换:
#define M 100
  1. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
  2. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
  3. 宏参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  4. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
    例如:
#define M 100
printf("the value is M");

在这里插入图片描述

宏与函数的对比

宏通常被应用于执行简单的运算。
比如在两个数中找出较大的⼀个时,写成下面的宏,更有优势⼀些。

#define MAX(a, b) ((a)>(b)?(a):(b))

有人会说函数编写起来也很简单,为什么说宏会更好?
原因有⼆:

  1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜⼀筹。
  2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用> 来比较的类型。宏的参数和类型无关。

和函数相比宏的劣势:
每次使用宏的时候,⼀份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度。
宏是没法调试的。
宏由于类型无关,也就不够严谨。
宏可能会带来运算符优先级的问题,导致程容易出现错。

宏有时候可以做函数做不到的事情。比如:宏的参数可以出现类型,但是函数做不到。

#define MALLOC(num, type)\(type*)malloc(num * sizeof(type))...
//使⽤MALLOC(10, int);//类型作为参数
//预处理器替换之后:(int*)malloc(10 * sizeof(int));

宏与函数的对比(这个是参考的素材,所以有水印请谅解):

在这里插入图片描述


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

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

相关文章

2024-10-30 学习人工智能的Day18

Python包和模块 当使用Python编程时,包(Packages)和模块(Modules)是两个关键的概念,它们有助于组织、管理和复用代码。 1. 模块(Modules) 1.1 什么是模块 一个.py 文件就是一个模…

从 TCP 友好性看传输优化

再看一遍最传统 TCP AIMD 吞吐的推导: 这个积分用离散求和表示很简单,一个锯齿发送的报文总数为: ( W 2 0 ) ( W 2 1 ) ( W 2 2 ) . . . ( W 2 ( W − W 2 ) ) ≈ 3 ⋅ W 2 8 (\dfrac{W}{2}0)(\dfrac{W}{2}1)(\dfrac{W}{2}2)...(\df…

css 对称按钮,中间斜平行间隔,两头半圆

序:稍一看,挺好看,看也简单,实现起来应该也是一样,没什么难度,分分钟完成。后面将其他的UI做了七七八八后,到这个按钮的时候,不知怎么,突然卡机了,想不起来怎…

DDRPHY数字IC后端设计实现系列专题之后端设计导入,IO Ring设计

本章详细分析和论述了 LPDDR3 物理层接口模块的布图和布局规划的设计和实 现过程,包括设计环境的建立,布图规划包括模块尺寸的确定,IO 单元、宏单元以及 特殊单元的摆放。由于布图规划中的电源规划环节较为重要, 影响芯片的布线资…

几种因素对磁控溅射AlN薄膜择优取向的影响

几种因素对磁控溅射AlN薄膜择优取向的影响 AlN材料在微电子产业中有广泛的应用,AlN薄膜在多种器件中都扮演着重要角色。 晶体生长中的择优取向是指在多晶材料中,晶粒沿着某一特定晶向或晶面生长得更快或更优先的现象。这种取向通常与材料的制备工艺和生长…

基于Java SpringBoot和Vue社区医院诊所医疗挂号管理系统设计

摘要 本文旨在设计并实现一个基于Java SpringBoot和Vue的社区医院管理系统,以解决当前社区医院管理中存在的效率低下、数据安全性差等问题。通过采用前后端分离架构,系统实现了用户信息管理、挂号管理、医生管理等功能模块,有效提升了医院的…

Linux 基础io_ELF_虚拟物理地址_动态库加载

1.可执行程序格式 ELF [wwshcss-ecs-178e myshell]$ ll total 56 -rw-rw-r-- 1 wws wws 92 Oct 17 19:14 file -rw-rw-r-- 1 wws wws 82 Oct 12 16:51 makefile -rw-r--r-- 1 wws wws 90 Oct 17 19:13 myfile -rwxrwxr-x 1 wws wws 20128 Oct 16 21:02 myshell -rw-r…

Java如何实现PDF转高质量图片

大家好,我是 V 哥。在Java中,将PDF文件转换为高质量的图片可以使用不同的库,其中最常用的库之一是 Apache PDFBox。通过该库,你可以读取PDF文件,并将每一页转换为图像文件。为了提高图像的质量,你可以指定分…

【HarmonyOS NEXT】使用 Navigation 对折叠屏设备页面进行分栏展示,优化 UI 交互

关键词:折叠屏、navigation、router、路由、分栏、UI 随着科技的发展,手机设备形态也由一面屏向多面屏进行发展,那么软件的UI适配也面临着问题,本篇文章主要解决大屏设备的页面 UI 适配问题,如折叠屏,平板&…

Coppelia Sim (v-REP)仿真 机器人3D相机手眼标定与实时视觉追踪 (二)

coppelia sim[V-REP]仿真实现 机器人于3D相机手眼标定与实时视觉追踪 二 zmq API接口python调用python获取3D相机的数据获取彩色相机的数据获取深度相机的数据用matpolit显示 python控制机器人运动直接控制轴的位置用IK运动学直接移动到末端姿态 相机内参的标定记录拍照点的位置…

Linux 安装nacos

1.下载版本 https://github.com/alibaba/nacos/tags 2.解压压缩包,启动 (1)将压缩包放到/usr/local目录下,解压 tar -xvf nacos-server-2.0.0-BETA.tar.gz(2)删除压缩包 rm -f nacos-server-2.0.0-BETA.tar.gz(3) 找到nacos的mysql的数据库脚本,在数…

sqoop问题汇总记录

此篇博客仅记录在使用sqoop时遇到的各种问题。持续更新,有问题评论区一起探讨,写得有不足之处见谅。 Oracle_to_hive 1. main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTr…

基于微信小程序的小区管理系统设计与实现(lw+演示+源码+运行)

摘 要 社会发展日新月异,用计算机应用实现数据管理功能已经算是很完善的了,但是随着移动互联网的到来,处理信息不再受制于地理位置的限制,处理信息及时高效,备受人们的喜爱。所以各大互联网厂商都瞄准移动互联网这个潮…

window11使用wsl2安装Ubuntu22.04

目录 1、快速了解wsl2 安装子系统linux流程(B站视频) 2、wsl2常用命令 3、windows与子系统Linux文件访问方法 4、子系统linux使用windows网络代理、网络配置(镜像网络,非NAT) 5、wsl2 Ubuntu miniconda 安装 6、…

【K8S系列】Kubernetes 中 NodePort 类型的 Service 无法访问的问题【已解决】

在 Kubernetes 中,NodePort 类型的 Service 允许用户通过每个节点的 IP 地址和指定的端口访问应用程序。如果 NodePort 类型的 Service 无法通过节点的 IP 地址和指定端口进行访问,可能会导致用户无法访问应用。本文将详细分析该问题的常见原因及其解决方…

Cyber​​Panel filemanager/upload 远程命令执行漏洞复现

0x01 产品简介 CyberPanel是一个开源的Web控制面板,它提供了一个用户友好的界面,用于管理网站、电子邮件、数据库、FTP账户等。CyberPanel旨在简化网站管理任务,使非技术用户也能轻松管理自己的在线资源。 0x02 漏洞概述 该漏洞源于filemanager/upload接口未做身份验证和…

(C#面向初学者的 .NET 的生成 AI) 第 2 部分-什么是 AI 和 ML?

从本部分开始Luis Quintanilla介绍AI和机器学习,需要学习的一些东西是什么是AI和ML?作为一名.net开发人员如何学习使用AI和ML。 1、首先什么是AI 和 ML? 你可以把它看作是基本相同事物的不同层次。 在顶层的是AI(人工智能&#xf…

Swarm-LIO: Decentralized Swarm LiDAR-inertial Odometry论文翻译

文章目录 前言一、介绍二、相关工作三、方法A. 问题表述B. 框架概述C. 群体系统的初始化D. 去中心化激光雷达-惯性状态估计 四. 实验A. 室内飞行B. 退化环境飞行C. 去中心化部署 五. 结论和未来工作 前言 原文:原文 准确的自我状态和相对状态估计是完成群体任务的关…

wsl 使用docker 部署oracle11g数据库

wsl 使用docker 部署oracle11g数据库 1. 下载oracle11g sudo docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g2. 运行oracle11g容器(docker-compose) services:oracle-1.0:container_name: oracle11gimage: oracle11g:1.0restart:…

IDEA集成JProfiler

目录 下载并安装JProfiler下载安装包管理员身份运行配置许可证邮箱复制注册码配置永久许可证选择IDE集成 在IDEA中下载并安装JProfiler插件启动并使用JProfiler进行性能分析启动Java应用程序:自动运行JProfiler 知识扩充功能 下载并安装JProfiler 下载安装包 官网…