当前位置: 首页 > news >正文

预处理详解


乐观学习,乐观生活,才能不断前进啊!!!

我的主页:optimistic_chen
我的专栏:c语言
点击主页:optimistic_chen和专栏:c语言,
创作不易,大佬们点赞鼓励下吧~

前言

这篇博客是C语言的收官之作,希望各方大佬多多支持。
作为运行程序必不可少的一部分,预处理在上篇博客中也有简单说明,本次我们来深入了解一下程序运行中预处理的作用吧,其中有的小细节对我的帮助很大,希望也可以帮助到你们!

文章目录

  • 前言
  • 预定义符号
  • #define定义常量
  • #define定义宏
    • 带有副作用的宏参数
    • 宏替换的规则
  • 宏与函数的对比
  • #运算符
  • 命名约定
  • #under
  • 条件编译
  • 头文件包含
    • 本地文件包含
    • 库函数包含
    • 嵌套文件包含
  • 完结

预定义符号

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

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

在这里插入图片描述

#define定义常量

一般形式:

#define name stuff

举例:

#define MAX 1000
#define reg register //为 register这个关键字,创建⼀个简短的名字)(后面链表名称会很方便)
#define CASE break;case //在写case语句的时候⾃动把 break写上。(switch语句)
// 如果定义的 stuff过⻓,可以分成⼏⾏写,除了最后⼀⾏外,每⾏的后⾯都加⼀个反斜杠(续⾏符)
#define DEBUG_PRINT printf(“file:%s\tline:%d\t
date:%s\ttime:%s\n” , __ FILE__ , __ LINE__ ,\
__ DATE__, __ TIME__ )

注意:在define定义标识符的时候,不要在最后加上 ;(分号)

#define定义宏

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

#define name( parament-list ) stuff
参数列表的左括号必须与name紧邻,如果两者之间有任何空⽩存在,参数列表就会被解释为stuff的⼀部分

代码示例:

#define SQUARE( x ) x * x
int main() {int a = 5;printf("%d\n", SQUARE(a + 1));
}

我们的想法是6*6=36,但是运行程序会发现结果为11
在这里插入图片描述
原因很简单,原语句被替换为

printf (“%d\n”,a + 1 * a + 1 );

我们把定义宏修改一下:

#define SQUARE(x) (x) * (x) 
int main() {int a = 5;printf("%d\n", SQUARE(a + 1));return 0;
}

在这里插入图片描述
这样结果就和我们想的一样了。

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

带有副作用的宏参数

当宏参数在宏的定义中出现超过⼀次的时候,如果参数带有副作⽤,那么你在使⽤这个宏的时候就可能出现危险,导致不可预测的后果。副作⽤就是表达式求值的时候出现的永久性效果

#include<stdio.h>
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
int main()
{int x = 5;int y = 8;int z = MAX(x++, y++);printf("x=%d y=%d z=%d\n", x, y, z);
}
---
z = ( (x++) > (y++) ? (x++) : (y++));

在这里插入图片描述

宏替换的规则

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

  1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先被替换。
  2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

注意:

  1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

宏与函数的对比

属性#define定义宏函 数
代码长度每次使用宏时,宏代码都会被插入到程序中,程序长度会大幅度增长函数代码只出现在一个地方,每次调用函数时,只调用同一个地方的程序
执行速度更快因为存在函数的调用和返回,额外开辟了内存,运行慢一点
操作符优先级宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,建议宏在书写时多些括号。函数参数只在函数调用的时候求值使用,结果值返回给函数
参数类型宏的参数与类型无关,只要对参数的操作是合法的,它就可以使用任何参数类型函数的参数与类型有关,不同的参数,就需要不同的函数
调试宏是不方便调试的函数是可以逐语句调试的
递归宏不能递归函数可以递归

#运算符

#运算符将宏的⼀个参数转换为字符串字⾯量,它仅允许出现在带参数的宏的替换列表中

#include<stdio.h>
#define PRINT(n) printf("the value of "#n " is %d\n", n)
int main()
{int a = 5;PRINT(a);printf("the value of ""a" " is %d", a);//当我们把a替换到宏的体内时,就出现了#a,⽽#a就是转换为"a"
}

在这里插入图片描述

命名约定

那我们平时的⼀个习惯是:
把宏名全部⼤写
函数名不要全部⼤写

(这对我们规范代码有很大帮助)~~

#under

这条指令用于移除一个宏定义

#undef NAME
//如果现存的⼀个名字需要被重新定义,那么它的旧名字⾸先要被移除。

我觉得我们初学者目前用到很少。

条件编译

在编译⼀个程序的时候我们如果要将⼀条语句(⼀组语句)编译或者放弃是很⽅便的。因为我们有条件编译指令

代码示例:

#include <stdio.h>
#define __DEBUG__
int main()
{int i = 0;int arr[10] = { 0 };for (i = 0; i < 10; i++){arr[i] = i;#ifdef  __DEBUG__printf("%d\n", arr[i]); //为了观察数组是否赋值成功。#endif //__DEBUG__}return 0;
}

在这里插入图片描述
这里展示一些常见的条件编译指令:

#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
//常量表达式由预处理器求值。//多个分⽀的条件编译
#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif判断是否被定义
#if defined(symbol)
#ifdef symbol#if !defined(symbol)
#ifndef symbol

头文件包含

本地文件包含

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

#include "stdio.h" 

库函数包含

直接去标准路径下去查找,如果找不到就提⽰编译错误
那有人可能会认为都可以使用“ ”的形式包含,可以一定是可以的,但是这样做查找的效率就低些,当然这样也不容易区分是库⽂件还是本地⽂件了

#include<stdio.h>

嵌套文件包含

#include 指令可以使另外⼀个⽂件被编译。
就像它实际出现于 #include 指令的地⽅⼀样

预处理器先删除这条指令,并⽤包含⽂件的内容替换。
⼀个头⽂件被包含10次,那就实际被编译10次,如果重复包含,对编译的压⼒就⽐较⼤。
如何解决头⽂件被重复引⼊的问题?
答案:条件编译。
每个头⽂件的开头写:

#ifndef __TEST_H__
#define __TEST_H__
//头⽂件的内容
#endif //__TEST_H__或者
#pragma once 

就可以避免头文件的重复引用。

完结

本次博客到此结束
祝开心每一天~~~
最后觉得博客有帮助,可以点点关注,支持一下,期待下次博客~~~

相关文章:

预处理详解

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 点击主页&#xff1a;optimistic_chen和专栏&#xff1a;c语言&#xff0c; 创作不易&#xff0c;大佬们点赞鼓…...

Python的创建和使用自定义模块

Python 的模块是组织代码的基本单元&#xff0c;它可以包含变量、函数、类等&#xff0c;并且可以被其他 Python 程序引用和重用。除了使用 Python 提供的标准库和第三方库外&#xff0c;开发者还可以创建自定义模块&#xff0c;用于组织和管理自己的代码。本文将详细介绍如何创…...

Python根据预设txt生成“你画我猜”题目PPT(素拓活动小工具)

Python根据预设txt生成“你画我猜”题目PPT&#xff08;素拓活动小工具&#xff09; 场景来源 去年单位内部的一次素拓活动&#xff0c;分工负责策划设置其中的“你画我猜”环节&#xff0c;网络上搜集到题目文字后&#xff0c;想着如何快速做成对应一页一页的PPT。第一时间想…...

小程序地理位置接口权限直接抄作业

小程序地理位置接口有什么功能&#xff1f; 随着小程序生态的发展&#xff0c;越来越多的小程序开发者会通过官方提供的自带接口来给用户提供便捷的服务。但是当涉及到地理位置接口时&#xff0c;却经常遇到申请驳回的问题&#xff0c;反复修改也无法通过&#xff0c;给的理由也…...

【Osek网络管理测试】[TG3_TC6]等待总线睡眠状态_2

&#x1f64b;‍♂️ 【Osek网络管理测试】系列&#x1f481;‍♂️点击跳转 文章目录 1.环境搭建2.测试目的3.测试步骤4.预期结果5.测试结果 1.环境搭建 硬件&#xff1a;VN1630 软件&#xff1a;CANoe 2.测试目的 验证DUT在满足进入等待睡眠状态的条件时是否进入该状态 …...

BEV下统一的多传感器融合框架 - FUTR3D

BEV下统一的多传感器融合框架 - FUTR3D 引言 在自动驾驶汽车或者移动机器人上&#xff0c;通常会配备许多种传感器&#xff0c;比如&#xff1a;光学相机、激光雷达、毫米波雷达等。由于不同传感器的数据形式不同&#xff0c;如RGB图像&#xff0c;点云等&#xff0c;不同模态…...

c#和python的flask接口的交互

一、灰度图像的传输 c#端的传输 //读入文件夹中的图像 Mat img2 new Mat(file, ImreadModes.AnyColor); //将图像的数据转换成和相机相同的buffer数据 byte[] image_buffer new byte[img2.Width * img2.Height]; int cn img2.Channels(); //通道数 if (cn 1){//将图像的数…...

Python测试框架Pytest的参数化详解

上篇博文介绍过&#xff0c;Pytest是目前比较成熟功能齐全的测试框架&#xff0c;使用率肯定也不断攀升。 在实际工作中&#xff0c;许多测试用例都是类似的重复&#xff0c;一个个写最后代码会显得很冗余。这里&#xff0c;我们来了解一下pytest.mark.parametrize装饰器&…...

KernelSU 如何不通过模块,直接修改系统分区

刚刚看了术哥发的视频,发现kernelSU通过挂载OverlayFS实现无需模块,即可直接修改系统分区,很是方便,并且安全性也很高,于是便有了这篇文章。 下面的教程与原视频存在差异,建议观看原视频后再结合本文章进行操作。 在未进行修改前,我们打开/system/文件夹,并在里面创建…...

红日靶场ATTCK 1通关攻略

环境 拓扑图 VM1 web服务器 win7&#xff08;192.168.22.129&#xff0c;10.10.10.140&#xff09; VM2 win2003&#xff08;10.10.10.135&#xff09; VM3 DC win2008&#xff08;10.10.10.138&#xff09; 环境搭建 win7&#xff1a; 设置内网两张网卡&#xff0c;开启…...

CellMarker | 人骨骼肌组织细胞Marker大全!~(强烈建议火速收藏!)

1写在前面 分享一下最近看到的2篇paper关于骨骼肌组织的细胞Marker&#xff0c;绝对的Atlas级好东西。&#x1f44d; 希望做单细胞的小伙伴觉得有用哦。&#x1f60f; 2常用marker&#xff08;一&#xff09; general_mrkrs <- c( MYH7, TNNT1, TNNT3, MYH1, MYH2, "C…...

游戏名台词大赏

文章目录 原神&#xff08;圈内&#xff09; 崩坏&#xff1a;星穹铁道&#xff08;圈内&#xff09; 崩坏3&#xff08;圈内&#xff09; 原神 只要不失去你的崇高&#xff0c;整个世界都会为你敞开。 总会有地上的生灵&#xff0c;敢于直面雷霆的威光。 谁也没有见过风&…...

OpenCV如何在图像中寻找轮廓(60)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV如何模板匹配(59) 下一篇 :OpenCV检测凸包(61) 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 cv::findContours使用 OpenCV 函数 cv::d rawContours …...

java 泛型题目讲解

泛型的知识点 泛型仅存在于编译时期&#xff0c;编译期间JAVA将会使用Object类型代替泛型类型&#xff0c;在运行时期不存在泛型&#xff1b;且所有泛型实例共享一个泛型类 public class Main{public static void main(String[] args){ArrayList<String> list1new Arra…...

pptx 文件版面分析-- python-pptx(python 文档解析提取)

安装 pip install python-pptx -i https://pypi.tuna.tsinghua.edu.cn/simple --ignore-installedpptx 解析代码实现 from pptx import Presentation file_name "rag_pptx/test1.pptx" # 打开.pptx文件 ppt Presentation(file_name) for slide in ppt.slides:#pr…...

http的basic 认证方式

写在前面 本文看下http的basic auth认证方式。 1&#xff1a;什么是basic auth认证 basic auth是一种http协议规范中的一种认证方式&#xff0c;即一种证明你就是你的方式。更进一步的它是一种规范&#xff0c;这种规范是这样子&#xff0c;如果是服务端使用了basic auth认证…...

【信息系统项目管理师练习题】信息系统治理

IT治理的核心是关注以下哪项内容? a) 人员培训和发展计划 b) IT定位和信息化建设与数字化转型的责权利划分 c) 业务流程的绩效管理 d) IT基础设施的优化利用 答案: b) IT定位和信息化建设与数字化转型的责权利划分 IT治理体系框架的组成部分包括以下哪些? a) IT战略目标、IT治…...

RabbitMQ之顺序消费

什么是顺序消费 例如&#xff1a;业务上产生者发送三条消息&#xff0c; 分别是对同一条数据的增加、修改、删除操作&#xff0c; 如果没有保证顺序消费&#xff0c;执行顺序可能变成删除、修改、增加&#xff0c;这就乱了。 如何保证顺序性 一般我们讨论如何保证消息的顺序性&…...

轻松上手的LangChain学习说明书

一、Langchain是什么&#xff1f; 如今各类AI模型层出不穷&#xff0c;百花齐放&#xff0c;大佬们开发的速度永远遥遥领先于学习者的学习速度。。为了解放生产力&#xff0c;不让应用层开发人员受限于各语言模型的生产部署中…LangChain横空出世界。 Langchain可以说是现阶段…...

【论文笔记】Training language models to follow instructions with human feedback A部分

Training language models to follow instructions with human feedback A 部分 回顾一下第一代 GPT-1 &#xff1a; 设计思路是 “海量无标记文本进行无监督预训练少量有标签文本有监督微调” 范式&#xff1b;模型架构是基于 Transformer 的叠加解码器&#xff08;掩码自注意…...

嵌入式交叉编译:x265

下载 multicoreware / x265_git / Downloads — Bitbucket 解压编译 BUILD_DIR${HOME}/build_libs CROSS_NAMEaarch64-mix210-linuxcd build/aarch64-linuxmake cleancmake \-G "Unix Makefiles" \-DCMAKE_C_COMPILER${CROSS_NAME}-gcc \-DCMAKE_CXX_COMPILER${CR…...

一、Redis五种常用数据类型

Redis优势&#xff1a; 1、性能高—基于内存实现数据的存储 2、丰富的数据类型 5种常用&#xff0c;3种高级 3、原子—redis的所有单个操作都是原子性&#xff0c;即要么成功&#xff0c;要么失败。其多个操作也支持采用事务的方式实现原子性。 Redis特点&#xff1a; 1、支持…...

C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等的介绍

文章目录 前言一、为什么存在动态内存管理二、动态内存函数的介绍1. malloc函数2. 内存泄漏3. 动态内存开辟位置4. free函数5. calloc 函数6. realloc 函数7. realloc 传空指针 总结 前言 C语言动态内存管理malloc、calloc、realloc、free函数、内存泄漏、动态内存开辟的位置等…...

最近惊爆谷歌裁员

Python团队还没解散完&#xff0c;谷歌又对Flutter、Dart动手了。 什么原因呢&#xff0c;猜测啊。 谷歌裁员Python的具体原因可能是因为公司在进行技术栈的调整和优化。Python作为一种脚本语言&#xff0c;在某些情况下可能无法提供足够的性能或者扩展性&#xff0c;尤其是在…...

音频可视化:原生音频API为前端带来的全新可能!

音频API是一组提供给网页开发者的接口&#xff0c;允许他们直接在浏览器中处理音频内容。这些API使得在不依赖任何外部插件的情况下操作和控制音频成为可能。 Web Audio API 可以进行音频的播放、处理、合成以及分析等操作。借助于这些工具&#xff0c;开发者可以实现自定义的音…...

【中等】保研/考研408机试-动态规划1(01背包、完全背包、多重背包)

背包问题基本上都是模板题&#xff0c;重点&#xff1a;弄熟多重背包模板 dp[j]max(dp[j-v[i]]w[i],dp[j]) //核心思路代码&#xff08;一维数组版&#xff09; dp[i][j]max(dp[i-1][j], dp[i-1][j-v[i]]w[i])//二维数字版 一、 0-1背包 一般输入两个变量&#xff1a;体积&…...

[DEMO]给两个字符串取交集的词语

要求&#xff1a;2个英文字符串中&#xff0c;取相同的大于等于4个字母的词组 比如&#xff1a; 字符串1&#xff1a;" xingMeiLingabcdef WorldHello", 字符串2&#xff1a;"mnjqlup WorldLingLing xingMeiLingHello" 获取交接&#xff1a; [xingMeiLing…...

leetcode53-Maximum Subarray

题目 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&#xf…...

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现 目录...

【go项目01_学习记录06】

学习记录 1 使用中间件1.1 测试一下1.2 push代码 2 URI 中的斜杆2.1 StrictSlash2.2 兼容 POST 请求 1 使用中间件 代码中存在重复率很高的代码 w.Header().Set("Content-Type", "text/html; charsetutf-8")统一对响应做处理的&#xff0c;我们可以使用中…...

大前端Wordpress图片主题/许昌seo推广

前言 前段时间做了一个爬取妹子套图的小功能&#xff0c;小伙伴们似乎很有兴趣&#xff0c;为了还特意组建了一个Python兴趣学习小组&#xff0c;来一起学习。十个python九个爬&#xff0c;在大家的印象中好像Python只能做爬虫。然而并非如此&#xff0c;Python 也可以做Web开发…...

怎么百度做网站/百度账号24小时人工电话

两种方式的区别 一、 # coding:utf-8 定义源代码的编码. 如果没有定义, 改源码中是不可以包含中文字符串的. 官方链接&#xff1a;https://www.python.org/dev/peps/pep-0263/ 二、sys.getdefaultencoding() 是设置默认的string的编码格式。 另外&#xff1a; 在python2…...

网站建设的开票编码/seo中文含义是什么

将oracle中的数据倒入postgresql...

做网站优化排名/深圳网络推广外包

随着无限火力自选模式的开启&#xff0c;许多小伙伴也沉迷在组队开黑的快乐中。而这次由于有Ban位的存在&#xff0c;所以除了最热门的猫咪外&#xff0c;一部分冷门英雄也正在崛起中。悠米悠米绝对是非BAN必选的存在&#xff0c;只要队友稍微选一些肉装坦克&#xff0c;或是灵…...

dedecms政府网站模板/chatgpt 网址

目录 一、 编写脚本 1.创建脚本 2.写入命令 3.执行脚本文件 二、 设置定时执行本脚本。 1. 安装crond 2. 修改crontab内容 3. 重新启动crond服务 补充说明&#xff1a; 一、编写脚本 编写一个脚本文件&#xff0c;使脚本可以执行备份命令。 例如&#xff0c;将文件目…...

中铁建设集团个人门户网/郑州seo教程

Android自定义View的构造函数自定义View是Android中一个常见的需求&#xff0c;每个自定义的View都需要实现三个基本的构造函数&#xff0c;而这三个构造函数又有两种常见的写法。第一种每个构造函数分别调用基类的构造函数&#xff0c;再调用一个公共的初始化方法做额外初始化…...