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

C语言-预处理详解

1.预处理符号

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

__FILE__//代表当前进行编译的源文件
__LINE__//文件当前行号
__DATE__//文件当前日期
__TIME__//文件当前时间
__STDC__//如果编译器遵循ANSIC,其值为1,否则未定义

接下来,我们可以试验一下:

#include<stdio.h>int main()
{printf("%s\n",__FILE__);printf("%s\n",__DATE__);printf("%s\n",__TIME__);printf("%d\n",__LINE__);return 0;   
}

经过预处理之后,代码变成了:

int main()
{printf("%s\n","test.c");//目前在编译的文件名printf("%s\n","July 19 2024");printf("%s\n","18:17:54");printf("%d\n",8);return 0;
}

2.#define定义字符常量

基本语法:

                #define 名字 内容

即 #define name stuff

例子:

#define MAX 1000
#define reg register//为register这个关键字创了一个简短的名字
#define do_forever for(;;)//变成死循环了
#define CASE break;case//在写case语句时自动把break写上
//如果定义的语句过长,可以分成几行写,除最后一行外,每行最后都要加上一个反斜杠'\'(续行符)。注意:其后不能有空格,应直接回车,否则,续的就不是原来的语句了。
#define DEBUG_PRINT printf("file:%s\tline:%d\t\date:%s\ttime:%s\n",\__FILE__,__LINE__,    \__DATE__,__TIME__)

            

思考:

在define定义标识符的时候,如果在末尾加上‘;’怎样?

比如:

#define MAX 1000
#define MAX 1000;

建议不要加‘;’,因为可能会导致一些问题。

例:

当用了:

printf("%d\n",MAX);

就会出问题。

如果是这个:

if(condition)max=MAX;
elsemax=0;

那么等替换之后,if和else之间就是两条语句,而没有大括号时if和else后面只能接一条语句,else就不知道是和哪个else匹配的,就会出现语法错误。

3.#define定义宏

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

下面是其

定义方式:

#define name(parament-list) stuff

其中的parament-list是一个由逗号隔开的符号表,带表参数,它可能出现在stuff中。

注意:

        参数列表的左括号必须与name紧邻,如果二者之间有任何的空白存在,参数列表就会解释为stuff的一部分。

举例:

#define f(x) x*x

4.带有副作用的宏参数

所谓的副作用就是在实现预想的结果的同时,影响了其他的结果。

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预料的后果。

例如:

#define MAX(a,b) ((a)>(b)?(a):(b))
.....
int x=5;
int y=8;
int z=MAX(x++,y++);

5.宏替换的规则

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

1.在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,他们首先被替换。

2.替换的文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值替换。

3.最后,再对结果文本进行扫描,看看它是否包含任何由#define定义的符号。如果是,则重复上述处理过程。

注意:

1.宏参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。

2.当预处理器搜索#define定义的符号时,字符串常量的内容并不被搜索。

例:

#define M 10

但是“MARY"中的M是不会被替换的。

6.宏与函数的对比

宏通常被应用于执行简单的运算。

比如在两个数中找到较大数。

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

而如果用函数来完成,有一下缺点:

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

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

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

#define MALLOC(num,type) (type*)malloc(num*sizeof(type))

和函数相比,宏的劣势:

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

2.宏没法调试

3.宏由于是类型无关的,不够严谨。

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

至于第四点,有个例子:

#define MAX(a,b) a*b
//当a=3+1 b=1+2时

7.#和##

一.#

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

‘#'运算符所执行的操作可以理解为“字符串量化”。

适用场景:

当我们想要打印出“The value of x is %d"的情况

例如:

The value of b is 12
The value of a is 1

而以上的语句大致相同,需要改变的是某个数据的名字以及数据的具体大小。

为了方便后面的讲解,我们需要补充一个知识点:

在c语言中,printf("Hello world!")与printf("Hello""world!”)的结果是一样的。

回到原来的问题:我们把这个语句定义为宏

即:

#define PRINT(n) printf("The value of"#x"is%d\n",x);

当我们使用这个宏时:

int a=1;
PRINTF(a);

就会变成:

The value of a is 1

而#x就是将x转化为"x"这个字符串。

如果还想在字符串中加一些内容,可以直接#内容。

注意:我们需要使用这个符号的一个原因是:宏在替换时,不会替换字符串内的内容。

二.##

'##'字符用在宏定义里可以把两个符号粘连在一起,合成一个符号。被称为记号粘合。

这样的连接产生的标识符必须是合法的,否则就是未定义的。

它有如下应用场景:

当我们想要找出两个数中的较小数时,不同的数据类型得写不同的函数,但是,这样的函数结构是类似的,于是,我们就想到用宏,然而,这些不同函数的名称也要随着参数改变,同时要是合法的,而宏的参数只有一个,那就是类型,所以,我们想到用记号粘合。

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

改法:

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

具体使用:

TYPE_MAX(int)
//在预编译中替换为:
//int_max(int x,int y)
//{
//   return x>y?x:y;
}
TYPE_MAX(float)
//在预编译中替换为:
//float float_max(float x,float y)
//{
//    return x>y?x:y;
//}int main()
{int m=int_max(2,3);float n=float_max(3.5f,4.5f);return 0;
}

8.命名约定

由于宏与函数的使用语法相似,所以语言上无法帮我们区分二者,所以我们通常用一下命名习惯区分:

1.宏的全名全部大写。

2.函数名不要全部大写。

当然,这个规定不一定要遵守,c语言本身就有一些没有遵守,例如:

offsetof———宏:计算结构体成员相较于结构体起始位置的偏移量。

9.#undef

这个指令用于移除一个宏定义。是可以直接写入主函数的,不过需要注意的是:它与#define相同,不用单独加';'来表示语句的结束。

例如:

#define NAME 10int main()
{#undef NAMEreturn 0;
}

10.命令行定义

许多编译器提供了一种能力,允许在命令行中定义符号,用于启动编译过程。

例如:当我们根据同一个源文件要编译出一个程序的不同版本时,这个能力就能起到作用。

假如某个程序中声明了一个某长度的数组,如果机器的内存有限,我们需要一个很小的数组,但是另一个机器的内存大些,我们需要一个更大的数组时,就可以利用这个能力。

好处:代码可以根据需求快速调整。

11.条件编译

利用条件编译指令我们可以很方便的编译或放弃一条或一组语句。

例如:某些语句起到的是调试作用,我们希望在某些条件下使用。

#define _DEBUG_//当不想要ifdef后面的语句时,就注释掉这句int main()
{#ifdef _DEBUG_printf("6\n");#endifreturn 0;
}

常见的条件编译指令:

#if 常量表达式 //如果为假,后面的语句就不参与编译//...
#endif
//注意:一定要以#endif结尾//多分支条件编译#if 常量表达式//...
#elif 常量表达式//...
#else//...
#endif//判断是否被定义
#if defined(symbol)
#ifdef symbol#if !definede(symbol)
#ifndef symbol

注意:这些指令是可以相互嵌套的

12.头文件的包含

一.本地文件的包含:

#include"filename"

查找方式:先在源文件下的目录里找,如果该文件未被找到,编译器就会像找库函数一样在标准位置查找头文件。

如果找不到就显示编译错误。

二.库文件包含

#include<filename>

查找方式:直接在标准文件下查找,如果找不到就提示编译错误。

当然,库文件也可以用""包含,不过,这样的话效率就会低一些,也会没那么容易区分本地文件和库文件。

三.嵌套文件的包含

如果一个同文件被多次包含,编译器在预处理时就会多次替换头文件的内容,这样的重复包含对编译的压力很大。所以,我们可以使用一些方法避免这样的情况出现。

利用条件编译防止重复包含。

方法一:

在每个头文件里加上:

#ifndef __TEST_H__
#define __TEST_H__
//头文件中的内容
#endif

方法二:

在每个头文件中加上:

#pragma once

13.其他预处理指令

目前不想写了,可参考《C语言深度剖析》这本书。

相关文章:

C语言-预处理详解

1.预处理符号 C语言中设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号是在预处理期间处理的。 __FILE__//代表当前进行编译的源文件 __LINE__//文件当前行号 __DATE__//文件当前日期 __TIME__//文件当前时间 __STDC__//如果编译器遵循ANSIC&#xff0c;…...

计算机网络-VLAN间通信(三层通信)模拟实现

目录 VLAN基础知识VLAN和普通LAN区别划分VLAN的原因 实现VLAN间的通信&#xff08;三层通信&#xff09;方案一&#xff1a;多臂路由方案二&#xff1a;单臂路由方案三&#xff1a;三层交换机 VLAN基础知识 VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网…...

【JAVA】数据类型及变量

&#x1f389;欢迎大家收看&#xff0c;请多多支持&#x1f339; &#x1f970;关注小哇&#xff0c;和我一起成长&#x1f680;个人主页&#x1f680; Java的数据类型 可以分为两类&#xff0c;基本数据类型和引用数据类型 基本数据类型有4类8种&#xff0c;4类分别是整型 浮…...

微软蓝屏事件暴露的网络安全问题

目录 1.概述 2.软件更新流程中的风险管理和质量控制机制 2.1.测试流程 2.2.风险管理策略 2.3.质量控制措施 2.4.小结 3.预防类似大规模故障的最佳方案或应急响应对策 3.1. 设计冗余系统 3.2. 实施灾难恢复计划 3.3. 建立高可用架构 3.4. 类似规模的紧急故障下的响应…...

11 - FFmpeg - 编码 AAC

Planar 模式是 ffmpeg内部存储模式&#xff0c;我们实际使用的音频文件都是Packed模式的。 FFmpeq解码不同格式的音频输出的音频采样格式不是一样。 其中AAC解码输出的数据为浮点型的 AV_SAMPLE_FMT_FLTP 格式&#xff0c;MP3 解码输出的数据为 AV_SAMPLE_FMT_S16P 格式(使用的…...

OS Copilot初体验的感受与心得

本文介绍体验操作系统智能助手OS Copilot后&#xff0c;个人的一些收获、体验等。 最近&#xff0c;抽空体验了阿里云的操作系统智能助手OS Copilot&#xff0c;在这里记录一下心得与收获。总体观之&#xff0c;从个人角度来说&#xff0c;感觉这个OS Copilot确实抓住了不少开发…...

Ajax学习笔记

文章目录标题 Ajax学习笔记axios使用axios请求拦截器axios响应拦截器优化axios响应结果 form-serialize插件图片上传HTTP协议请求报文相应报文接口文档 AJAX原理 - XMLHttpRequest使用XMLHttpRequestXMLHttpRequest - 查询参数查询字符串对象 XMLHttpRequest - 数据提交 事件循…...

医学深度学习与机器学习融合的随想

医学深度学习与机器学习融合的随想 近年来&#xff0c;深度学习&#xff08;图像类&#xff09;和机器学习在医学领域的应用取得了飞速发展&#xff0c;为医学影像分析、疾病诊断和预后预测等领域带来了革命性的变革。深度学习擅长从复杂数据中提取高层次特征&#xff0c;而机…...

坑人的macos tar 命令 (实际上是bsdtar)换用 gnu tar

周末 看着笔记本上好用的朗文当代高级词典(mac版)和其它两部词典&#xff0c;准备复制到黑苹果台式机上去。考虑到词典内容有太多小文件&#xff0c;普通复制传输太慢&#xff0c;毫无疑问用 tar 打包肯定快而且能保留原始文件的各种信息。命令如下&#xff1a; time tar czf …...

【SpringBoot3】全局异常处理

【SpringBoot3】全局异常处理 一、全局异常处理器step1&#xff1a;创建收入数字的页面step2:创建控制器&#xff0c;计算两个整数相除step3:创建自定义异常处理器step5&#xff1a;创建给用提示的页面step6&#xff1a;测试输入&#xff08;10/0&#xff09; 二、BeanValidato…...

vue-Treeselect

一、Node KeyTypeDescriptionid (required)Number | String用于标识树中的选项。其值在所有选项中必须是唯一的label (required)String用于显示选项childrennode[] | null声明一个分支节点。你可以&#xff1a; 1&#xff09; 设置为由a组成的子选项数组。叶节点&#xff0c;b…...

【机器学习框架TensorFlow和PyTorch】基本使用指南

机器学习框架TensorFlow和PyTorch&#xff1a;基本使用指南 目录 引言TensorFlow概述 TensorFlow简介TensorFlow的基本使用 PyTorch概述 PyTorch简介PyTorch的基本使用 TensorFlow和PyTorch的对比结论 引言 随着深度学习的快速发展&#xff0c;机器学习框架在实际应用中起到…...

matlab 中的methods(Access = protected) 是什么意思

gpt版本 在 MATLAB 中&#xff0c;methods 是用于定义类方法的一部分。(Access protected) 是一种访问控制修饰符&#xff0c;它限制了方法的访问权限。具体来说&#xff0c;当你在类定义中使用 methods(Access protected) 时&#xff0c;你是在定义只有类本身及其子类可以访…...

【漏洞复现】Netgear WN604 downloadFile.php 信息泄露漏洞(CVE-2024-6646)

0x01 产品简介 NETGEAR WN604是一款由NETGEAR&#xff08;网件&#xff09;公司生产的无线接入器&#xff08;或无线路由器&#xff09;提供Wi-Fi保护协议&#xff08;WPA2-PSK, WPA-PSK&#xff09;&#xff0c;以及有线等效加密&#xff08;WEP&#xff09;64位、128位和152…...

图像处理 -- ISP调优(tuning)的步骤整理

ISP调优流程培训文档 1. 硬件准备 选择合适的图像传感器&#xff1a;根据项目需求选择合适的传感器型号。搭建测试环境&#xff1a;包括测试板、光源、色彩卡和分辨率卡等。 2. 初始设置 寄存器配置&#xff1a;初始化传感器的寄存器设置&#xff0c;包括曝光、增益、白平衡…...

【中项】系统集成项目管理工程师-第4章 信息系统架构-4.2系统架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…...

node.js中nodemon : 无法加载和使用问题,这是由于windows安全策略影起的按如下操作即可

1、用管理员权限打开vscode 2、文件终端中打开&#xff0c;输入 Set-ExecutionPolicy -Scope CurrentUser 3、再输入RemoteSigned 4、使用get-ExecutionPolicy查看权限&#xff0c;可以看到变为了RemoteSigned 重启问题解决...

【SD】 Stable Diffusion(SD)原理详解与ComfyUI使用 2

Stable Diffusion&#xff08;SD&#xff09;原理详解与ComfyUI使用 Stable Diffusion&#xff08;SD&#xff09;原理详解与ComfyUI使用1. SD整体结构2. Clip&#xff08;文本编码器&#xff09;3. Unit&#xff08;生成模型&#xff09;4. VAE&#xff08;变分自编码器&#…...

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(七)-广播远程识别码(Broadcast Remote ID)

目录 引言 5.5 广播远程识别码&#xff08;Broadcast Remote ID&#xff09; 5.5.1 使用PC5的广播远程识别码 5.5.2 使用MBS的广播远程识别码 引言 3GPP TS 23.256 技术规范&#xff0c;主要定义了3GPP系统对无人机&#xff08;UAV&#xff09;的连接性、身份识别、跟踪及…...

VMware 虚拟机 ping 不通原因排查

目录 一、检查网络 二、重启虚拟机网络 因为最近遇到了一个比较奇怪的 ping 不通虚拟机的事&#xff0c;在此过程中&#xff0c;检查了很多的设置&#xff0c;故而写一篇文章记录下&#xff0c;如有 VMware 虚拟机 ping 不通可以尝试本文的排查方式。 下面以 VMware 虚拟机为…...

websocket状态机

websocket突破了HTTP协议单向性的缺陷&#xff0c;基于HTTP协议构建了双向通信的通道&#xff0c;使服务端可以主动推送数据到前端&#xff0c;解决了前端不断轮询后台才能获取后端数据的问题&#xff0c;所以在小程序和H5应用中被广泛使用。本文主要集合报文分析对于websocket…...

JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】

JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】 目录 JCR一区级 | Matlab实现CPO-Transformer-LSTM多变量回归预测【2024新算法】效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现CPO-Transformer-LSTM多变量回归预测…...

力扣3226 使两个整数相等的位更改次数

写的代码&#xff1a; class Solution { public:string cc(int num){string res"";while(num>0){int rnum % 2;resstatic_cast<char>(48r)res;num/2;}return res;}int minChanges(int n, int k) {int res0;string n2cc(n);string k2cc(k);int n_sizen2.siz…...

VLAN 划分案例详解

vlan 的应用在网络项目中是非常广泛的&#xff0c;基本上大部分的项目都需要划分 vlan&#xff0c;这里从基础的 vlan 的知识开始&#xff0c;了解 vlan 的划分原理。 为什么需要 vlan&#xff1a; 1、什么是 VLAN&#xff1f; VLAN&#xff08;Virtual LAN&#xff09;&…...

[技术总结] C++ 使用经验

const 和 constexpr 有什么区别. const 一般是设置一个只读的属性, 在运行时还有可能通过cast变成一个可修改的. 但是constexpr是告诉编译器这就是一个常亮, 在编译时就可以计算出来然后进行替换.static 修饰的成员函数 & 成员变量 static 修饰的成员函数只能访问 static 修…...

音频数据集

1 多语言 Mozilla Common Voice 下载地址&#xff1a;https://voice.mozilla.org/data 时长&#xff1a;1965小时&#xff08;目前为止&#xff09; 最早2017年发布&#xff0c;持续更新&#xff0c;该基金会表示&#xff0c;通过 Common Voice 网站和移动应用&#xff0c;他们…...

Java | Leetcode Java题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; class Solution {public int missingNumber(int[] nums) {int n nums.length;int total n * (n 1) / 2;int arrSum 0;for (int i 0; i < n; i) {arrSum nums[i];}return total - arrSum;} }...

指针!!C语言(第二篇)

目录 一. 数组名的理解 二. 一维数组传参的本质 三. 冒泡排序法 四. 二级指针与指针数组 五. 字符指针变量与数组指针 一. 数组名的理解 在我们对指针有了初步的理解之外&#xff0c;今天我们来掌握一些新的知识就是数组与指针&#xff0c;第一个对数组名的了解&#xff…...

AIGC-ToonCrafter: Generative Cartoon Interpolation

论文:https://arxiv.org/pdf/2405.17933 代码:https://doubiiu.github.io/projects/ToonCrafter 给定首尾帧&#xff0c;生成逼真生动的动画 MOTIVATION Traditional methods which implicitly assume linear motion and the absence of complicated phenomena like disoccl…...

牛奶供应(三)

一个字贪&#xff0c;第一天&#xff0c;只能选择制作方式&#xff0c;后面的每一天&#xff0c;在<今天制作>与<前期存储>之间取更优解 例如样例&#xff1a;100 5&#xff0c;200 5&#xff0c;90 20&#xff0c;存储成本为10 第1天&#xff1a; 一定是制作&…...

建设企业网站进去无法显示/百度一下网页版搜索引擎

物联网安全风险分析 物联网( the Intemnet of Things, IoT)是近些年提出的概念&#xff0c;在实际应用中&#xff0c;可以把感应器、处理器和无线通信模块嵌入或装备到电网、铁路、桥梁、隧道、公路、建筑等各种物体中&#xff0c;使它们相互连接&#xff0c;构成物联网。它有…...

专门给小公司做网站/竞价托管公司联系方式

【问题现象】 由于排查问题&#xff0c;需要在release版本上暂时打开log输出。 【问题分析】 在gradle中打开调试即可&#xff0c;比如app.gradle文件中的 buildTypes { release { debuggable true zipAlignEnabled true //Zipalign优化 mi…...

asp.net做网站后台/香港疫情最新情况

Boris FX Continuum Complete 2020又简称BCC插件2020&#xff0c;是为Adobe软件和OFX而开发的视频特效插件&#xff0c;该插件能够为用户提供了丰富的特效&#xff0c;类型多样&#xff0c;拥有图像恢复&#xff0c;拉伸文本&#xff0c;处理标题和3D对象&#xff0c;色调调节&…...

广东网站建设熊掌号/北京度seo排名

什么是coredump&#xff1f; 通常情况下coredmp包含了程序运行时的内存&#xff0c;寄存器状态&#xff0c;堆栈指针&#xff0c;内存管理信息等。可以理解为把程序工作的当前状态存储成一个文件。许多程序和操作系统出错时会自动生成一个core文件。 如何使用coredump? coredu…...

中国建设人才服务信息网是正规网站/seo专业培训中心

蜻蜓特派员Windows XP SP3 纯净安装版 终结版&#xff0c;系统纯净无广告、无插件&#xff0c;网卡等驱动和运行库齐全&#xff0c;安全更新补丁全网最新&#xff01;微软停止了 Windows XP 的支持之后还是偶尔为 WinXP 提供了更加安全的使用环境。看到网上上很多“最终版”&am…...

微网站做的比较好/山西网络营销seo

1 定义 1.1输入 对于节点i的特征描述为xi,构成整个图的特征矩阵X &#xff0c;N行D列&#xff0c;N为节点数&#xff0c;D为特征数对于图的结构描述也为矩阵&#xff0c;一般为邻接矩阵A 1.2输出 输出结果为节点层次的矩阵Z&#xff0c;N行F列&#xff0c;F为每个节点的输出…...