C语言编程—预处理器
预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C Preprocessor)简写为 CPP。
所有的预处理器命令都是以井号(#)开头。它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始。下面列出了所有重要的预处理器指令:
预处理器实例
分析下面的实例来理解不同的指令。
#define MAX_ARRAY_LENGTH 20
这个指令告诉 CPP 把所有的 MAX_ARRAY_LENGTH 定义为 20。使用 #define 定义常量来增强可读性。
#include <stdio.h>
#include "myheader.h"
这些指令告诉 CPP 从系统库中获取 stdio.h,并添加文本到当前的源文件中。下一行告诉 CPP 从本地目录中获取 myheader.h,并添加内容到当前的源文件中。
#undef FILE_SIZE
#define FILE_SIZE 42
这个指令告诉 CPP 取消已定义的 FILE_SIZE,并定义它为 42。
#ifndef MESSAGE#define MESSAGE "You wish!"
#endif
这个指令告诉 CPP 只有当 MESSAGE 未定义时,才定义 MESSAGE。
#ifdef DEBUG/* Your debugging statements here */
#endif
这个指令告诉 CPP 如果定义了 DEBUG,则执行处理语句。在编译时,如果您向 gcc 编译器传递了 -DDEBUG 开关量,这个指令就非常有用。它定义了 DEBUG,您可以在编译期间随时开启或关闭调试。
预定义宏
ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。

让我们来尝试下面的实例:
#include <stdio.h>main()
{printf("File :%s\n", __FILE__ );printf("Date :%s\n", __DATE__ );printf("Time :%s\n", __TIME__ );printf("Line :%d\n", __LINE__ );printf("ANSI :%d\n", __STDC__ );}
当上面的代码(在文件 test.c 中)被编译和执行时,它会产生下列结果:
File :test.c
Date :Jun 2 2012
Time :03:36:24
Line :8
ANSI :1
预处理器运算符
C 预处理器提供了下列的运算符来帮助您创建宏:
宏延续运算符(\)
一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符(\)。例如:
#define message_for(a, b) \printf(#a " and " #b ": We love you!\n")
字符串常量化运算符(#)
在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表。例如:
#include <stdio.h>#define message_for(a, b) \printf(#a " and " #b ": We love you!\n")int main(void)
{message_for(Carole, Debra);return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Carole and Debra: We love you!
标记粘贴运算符(##)
宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。例如:
#include <stdio.h>#define tokenpaster(n) printf ("token" #n " = %d", token##n)int main(void)
{int token34 = 40;tokenpaster(34);return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
token34 = 40
这是怎么发生的,因为这个实例会从编译器产生下列的实际输出:
printf ("token34 = %d", token34);
这个实例演示了 token##n 会连接到 token34 中,在这里,我们使用了字符串常量化运算符(#)和标记粘贴运算符(##)。
defined() 运算符
预处理器 defined 运算符是用在常量表达式中的,用来确定一个标识符是否已经使用 #define 定义过。如果指定的标识符已定义,则值为真(非零)。如果指定的标识符未定义,则值为假(零)。下面的实例演示了 defined() 运算符的用法:
#include <stdio.h>#if !defined (MESSAGE)#define MESSAGE "You wish!"
#endifint main(void)
{printf("Here is the message: %s\n", MESSAGE); return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Here is the message: You wish!
参数化的宏
CPP 一个强大的功能是可以使用参数化的宏来模拟函数。例如,下面的代码是计算一个数的平方:
int square(int x) {return x * x;
}
我们可以使用宏重写上面的代码,如下:
#define square(x) ((x) * (x))
在使用带有参数的宏之前,必须使用 #define 指令定义。参数列表是括在圆括号内,且必须紧跟在宏名称的后边。宏名称和左圆括号之间不允许有空格。例如:
#include <stdio.h>#define MAX(x,y) ((x) > (y) ? (x) : (y))int main(void)
{printf("Max between 20 and 10 is %d\n", MAX(10, 20)); return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Max between 20 and 10 is 20
使用#define含参时,参数括号很重要,如上例中省略括号会导致运算错误:
#include <stdio.h>#define square(x) ((x) * (x))#define square_1(x) (x * x)int main(void)
{printf("square 5+4 is %d\n", square(5+4)); printf("square_1 5+4 is %d\n", square_1(5+4)); return 0;
}
输出结果为:
square 5+4 is 81
square_1 5+4 is 29
原因:
square 等价于 (5+4)*(5+4)=81
square_1 等价于 5+4*5+4=29
用#define宏定义将a,b交换,不使用中间变量,两种方法实现swap(x,y);
#include <stdio.h>
#define MAX(x,y) ((x>y)?(x):(y))
#define SWAP1(x,y) {x=x+y;y=x-y;x=x-y;}
#define SWAP2(x,y) {x=x^y;y=x^y;x=x^y;}int main()
{int a,b;scanf("%d %d",&a,&b);printf("Max number is:%d\n",MAX(a,b));printf("交换前:x=%d,y=%d\n",a,b);SWAP1(a,b);printf("交换后:x=%d,y=%d\n",a,b);SWAP2(a,b);printf("再次交换后:x=%d,y=%d\n",a,b);return 0;
}
输出结果为:
2 4
Max number is:4
交换前:x=2,y=4
交换后:x=4,y=2
再次交换后:x=2,y=4
相关文章:
C语言编程—预处理器
预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器(C Preprocessor)简写为 CP…...
使用 Maya Mari 设计 3D 波斯风格道具(p1)
今天瑞云渲染小编给大家带来了Simin Farrokh Ahmadi 分享的Persian Afternoon 项目过程,解释了 Maya 和 Mari 中的建模、纹理和照明过程。 介绍 我的名字是西敏-法罗赫-艾哈迈迪,人们都叫我辛巴 在我十几岁的时候,我就意识到我喜欢艺术和创造…...
Redis分布式问题
Redis实现分布式锁 Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系Redis中可以使用SETNX命令实现分布式锁。当且仅当 key 不存在,将 key 的值设为 value。 若给定的 key 已经存在&…...
synchronized原理
目录 一、基本特点 二、加锁过程 2.1、偏向锁 2.2、轻量级锁 2.3、重量级锁 三、其它的优化操作 3.1、锁消除 3.2、锁粗化 一、基本特点 synchronized有以下特性: 开始是乐观锁,如果锁冲突频繁,就转换为悲观锁。开始是轻量级锁,…...
10G光模块能兼容千兆光口吗
当涉及到光网络设备和光模块的兼容性时,确保正确的匹配是至关重要的。本期文章内容,我们将探讨10G光模块与千兆光口之间的兼容性。 一、10G光模块和千兆光口的基本概念 首先,我们需要了解10G光模块和千兆光口的基本概念。10G光模块是一种用…...
css 显示省略号 和 动态显示省略号
省略是非常常见的功能。 简单的实现省略号 下面的代码就可以实现省略号,超过宽度的时候就会出现省略号 .text-name{//宽高是一定要设置的不然是会无效延伸的width: 200rpx;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}稍微复杂点的情况&#…...
LeetCode 1253. 重构 2 行二进制矩阵
【LetMeFly】1253.重构 2 行二进制矩阵 力扣题目链接:https://leetcode.cn/problems/reconstruct-a-2-row-binary-matrix/ 给你一个 2 行 n 列的二进制数组: 矩阵是一个二进制矩阵,这意味着矩阵中的每个元素不是 0 就是 1。第 0 行的元素之…...
【八股】【C++】内存
这里写目录标题 内存空间分配new和delete原理C有几种newmalloc / free 与 new / delete区别malloc和free原理?delete和delete[]区别?C内存泄漏malloc申请的存储空间能用delete释放吗?malloc、calloc函数、realloc函数C中浅拷贝与深拷贝栈和队列的区别C里…...
数据库G等待
> db^Cgbasedbtpc:~$ dbaccess db10 -Database selected.> call insert_t();Routine executed.Elapsed time: 811.630 sec 磁盘逻辑日志,无BUF库> ^Cgbasedbtpc:~$ gbasedbtpc:~$ dbaccess db10 -Database selected.> call insert_t();Routine executed.Elapse…...
PCB封装设计指导(一)基础知识
PCB封装设计指导(一)基础知识 PCB封装是PCB设计的基础,也是PCB最关键的部件之一,尺寸需要非常准确且精确,关系到设计,生产加工,贴片等后续一系列的流程。 下面以Allegro为例介绍封装创建前的一些基础知识 1.各个psm文件代表什么 mechanical symbol 是.bsm Package sy…...
Flask框架之Restful--介绍--下载--基本使用
目录 Restful 概念 架构的主要原则 适用场景 协议 数据传输格式 url链接规则 HTTP请求方式 状态码 Restful的基本使用 介绍 优势 缺点 安装 基本使用 注意 Restful 概念 RESTful(Representational State Transfer)是一种用于设计网络应用…...
2023年上海市浦东新区网络安全管理员决赛理论题样题
目录 一、判断题 二、单选题 三、多选题 一、判断题 1.等保1.0至等保2.0从信息系统拓展为网络和信息系统。 正确 (1)保护对象改变 等保1.0保护的对象是信息系统,等保2.0增加为网络和信息系统,增加了云计算、大数据、工业控制系统、物联网、移动物联技术、网络基础…...
SQL语言的四大组成部分——DCL(数据控制语言)
1️⃣前言 SQL语言中的DCL(Data Control Language)是一组用于控制数据库用户访问权限的语言,主要包括GRANT、REVOKE、DENY等关键字。 文章目录 1️⃣前言2️⃣DCL语言3️⃣GRANT关键字4️⃣REVOKE关键字5️⃣DENY关键字6️⃣总结附࿱…...
ChatGPT新功能曝光:可记住用户信息、上传文件和工作区
🦉 AI新闻 🚀 ChatGPT新功能曝光:可记住用户信息、上传文件和工作区 摘要:一张神秘截图曝光了ChatGPT新功能,包括可记住用户信息的"My profile"、上传和管理文件的"My files"以及可以让AI使用不…...
【Unity编辑器扩展】(三)PSD转UGUI Prefab, 一键拼UI解放美术/程序(完结)
工具效果: 第一步,把psd图层转换为可编辑的节点树,并自动解析UI类型、自动绑定UI子元素: 第二步, 点击“生成UIForm"按钮生成UI预制体 (若有UI类型遗漏可在下拉菜单手动点选UI类型): 验证一键生成UI效果: 书接上…...
SpringBoot开发Restful风格的接口实现CRUD功能
基于SpringBoot开发一个Restful接口 前言一、什么是SpringBoot?二、实战---基于SpringBoot开发一个Restful接口1.开发前的准备工作1.1 添加相关依赖 (pom文件) 1.2 创建相关数据库和表1.3 数据库配置文件 2.实战开发---代码逻辑2.1 实体类2.2…...
【Servlet学习三】实现一个内存版本的简易计算器~
目录 一、方式1:使用form表单的形式(不推荐) 🌈1、前端代码:HTML文件 🌈2、后端代码:Calculator_form.java文件 🌈3、最终效果 二、方式2:使用ajax形式(…...
Linux c语言获取本机网关 ip 地址
文章目录 前言一、获取本机网关 ip 地址1.1 代码示例1.2 代码详解介绍 二、使用Netlink套接字实时监控网络事件2.1 简介2.2 示例代码 前言 这篇文章写了获取本机的ip地址和子网掩码:Linux c语言获取本机 ip、子网掩码 一、获取本机网关 ip 地址 使用Netlink套接字…...
nginx部署本地项目如何让异地公网访问?服务器端口映射配置!
接触过IIS或apache的小伙伴们,对nginx是比较容易理解的,nginx有点类似,又有所差异,在选择使用时根据自己本地应用场景来部署使用即可。通过一些对比可能会更加清楚了解: 1.nginx是轻量级,比apache占用更少…...
云时代已至,新一代数据分析平台是如何实现的?
2023 年 5 月,由 Stackoverflow 发起的 2023 年度开发者调查数据显示,PostgreSQL 已经超越 MySQL 位居第一,成为开发人员首选。PostgreSQL 在国内的热度也越来越高。6 月 17 日,PostgreSQL 数据库技术峰会在成都顺利召开。本次大会…...
实战踩坑:在华为ENSP模拟器上配置OSPF NSSA区域,为什么外部路由没传出去?
华为ENSP模拟器中OSPF NSSA区域外部路由失效的深度排查指南 当你在华为ENSP模拟器中配置OSPF NSSA区域时,是否遇到过这样的困境:明明按照教程步骤操作,外部路由却像被黑洞吞噬一般无法传递到其他区域?本文将带你深入这个技术迷宫的…...
LSLib:从游戏资源新手到MOD制作专家的完整路径
LSLib:从游戏资源新手到MOD制作专家的完整路径 【免费下载链接】lslib Tools for manipulating Divinity Original Sin and Baldurs Gate 3 files 项目地址: https://gitcode.com/gh_mirrors/ls/lslib 你是否曾经想过修改《神界原罪》系列或《博德之门3》的游…...
Phi-4-mini-reasoning开源大模型教程:免配置镜像+128K长文本推理实战
Phi-4-mini-reasoning开源大模型教程:免配置镜像128K长文本推理实战 1. 模型简介 Phi-4-mini-reasoning是一个轻量级开源大语言模型,专注于高质量推理任务。作为Phi-4模型家族成员,它具备以下核心特点: 推理能力突出࿱…...
信创协同办公价格与成本:这样选,性价比直接拉满!
“一套信创协同办公到底多少钱?”“是按人头收费,还是按项目打包算?”“前期买着便宜,后期维护会不会无底洞?”不管是政企单位采购,还是企业选型,这三个问题几乎是所有人的核心顾虑。毕竟信创办…...
WSL2下USB串口设备‘失踪’?手把手教你找回/dev/ttyUSB0(以Quectel模块为例)
WSL2下USB串口设备消失的终极解决方案:从原理到实战 最近在WSL2环境下调试Quectel模块时,发现一个奇怪现象:lsusb明明能识别设备,但/dev/ttyUSB0却神秘失踪。这让我想起去年调试树莓派时遇到的类似问题,但WSL2的环境特…...
格式化字符串漏洞利用的5种常见手法:以CTFshow题目为例
格式化字符串漏洞实战:5种高级利用手法与CTFshow案例分析 格式化字符串漏洞(Format String Vulnerability)是二进制安全领域中最经典也最危险的漏洞类型之一。这种漏洞源于程序员错误地将用户输入直接作为格式化字符串参数传递给printf、spri…...
Windows 11 + CUDA 12.1 保姆级教程:手把手搞定Detectron2环境搭建(含Git加速与权限避坑)
Windows 11 CUDA 12.1 终极指南:零障碍搭建Detectron2开发环境 RTX 40系显卡用户注意了!如果你正在Windows 11上尝试搭建Detectron2开发环境,却苦于找不到针对CUDA 12.1的完整解决方案,这篇指南将为你扫清所有障碍。不同于网上那…...
【QT】-- QT操作数据库
前言: Qt是C一个开发框架,具有跨平台特性。这篇是作者大二学习的时候做的笔记,有可能有错误,请各位批评指正。这篇记录QT操作数据库。欢迎大家收藏 关注,作者将会持续更新。 文章目录Qt 操作数据库QSqlDatabase数据库…...
为什么你的Windows 11需要专业优化:4步高效解决方案
为什么你的Windows 11需要专业优化:4步高效解决方案 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and cust…...
智能表格在敏捷项目管理中的工时统计实践
1. 为什么敏捷团队需要智能工时统计 在敏捷开发中,两周一次的迭代就像一场短跑比赛。我见过太多团队在冲刺过半时才发现工时严重超支,这时候再调整已经来不及了。传统Excel表格需要手动更新公式,光是合并不同成员的工作量报表就能消耗半天时间…...
