预处理,咕咕咕

article/2025/8/27 10:54:48

1.预定义符号

_FILE_  //编译的源文件
_LINE_  //文件行号
_DATA_  //文件编译日期
_TIME_  //文件编译时间
_STDC_  //如果文件编译遵循ANSI C,其值为一,否则未定义
printf("%d",_FILE_,_LINE_);

2.#define定义常量

#define name stuff
#define MAX 1000
#define reg 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 MAX 1000;
if(condition)
max=MAX;
else
max=0;这里加了;        if与else之间有2个语句,没有{}时if后面只能有1条语句

3.#define 定义宏

#define机制包括了一个规定,允许把文本替换到文本中,这种实现称为宏或定义宏

#define name(parament-list) stuff是一个由逗号隔开的符号表,可能出现在stuff中
参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,
参数列表会被解释为stuff的一部分
#define SQUARE(x) x*x

输入5,打印5*5;

但是有问题

int a=5;
printf("%d",SQUARE(a+1));

但它不打印36,实际上替换为

printf("%d",a+1*a+1);
打印了11
#define SQUARE(x) (x)*(x)就可以解决了
printf("%d",(a+1)*(a+1));
#define double(x) (x)+(x)
printf("%d",10*double(5));   10*5+5
乘法先于宏定义
#define double(x) ((x)+(x))

用于数值表达式进行求值的宏定义应该用这种方法加上括号,避免在使用宏时由于参数中的操作符和临近操作符之间不可预料的相互作用

4.带有副作用的宏参数

当宏参数在宏的定义中出现超过一次后,如果参数带有副作用,那么使用时就可能有副作用

x+1没有副作用,x++有副作用

#define MAX(a,b) ((a)>(b)?(a):(b))
x=5;
y=8;
z=MAX(x++,y++);  ((x++)>(y++)?(x++):(y++))
6  10   9

5.宏替换的规则

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

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

3.最后对结果文件扫描检查是否有#define定义的符号,有就在重复

宏定义和#define定义中可以出现其他#define定义的符号,对于宏不能出现递归

当预处理器搜索#define定义的符号,字符串常量不被搜索

6.宏函数的对比

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

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

优势;

由于调用函数和从函数返回的代码可能比实际执行这个代码工作的时间要多,宏比函数在程序的规模和速度上更胜一筹

函数的参数必须声明特定的类型,函数只能在类型合适的表达式上使用,宏不需要定义类型

劣势:

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

宏没法调试

宏与类型无关,不够严谨

宏可能带来运算符优先级的问题,可能有误

宏的参数可以出现类型,但是函数做不到

#define MALLOC(num,type)\
(type )malloc(num sizeof(type))
MALLOC(10,int)   (int*)malloc(10 sizeof(int))

7.#和##

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

#所执行的操作可以理解为字符串化

#define PRINT(n) printf(" the "#n" is %d",n)
PRINT(a)   10
打印the a is 10

##可以把位于它两边的符号合成一个符号,它允许宏定义从分离的文本片段创建标识符,称为记号粘合,这样的链接必须产生一个合法的标识符,否则结果就是未定义的

int int_max(int x,int y)
{
return x>y?x:y:
}
float float_max(float a,float b)
{
return a>b?a:b;
}
#define GENERIC_MAX(type)   \
type type##_max(type x,type y) \
{
return (x>y?x:y); \
} 

一般来说有命名约定,宏名全部大写,函数名不要全部大写

#undef用于移除一个宏定义

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

10.命令行定义

允许在命令行中定义符号,用于启动编译过程。当我们要根据同一个源文件编译出一个程序的不同版本就有用。

#include<stdio.h>
int main()
{
int array{ARRAY_SIZE];
for(int i=0;i<ARRAT_SIZE;i++)
{
array[i]=i;
}
for(int i=0;i<ARRATY_SIZE;i++)
{
printf("%d",array[i]);
}
return 0;
}linux环境展示
gcc -D ARRAY_SIZE=10 programe.c

11.条件编译

因为有条件编译指令,在编译一个程序时我们如果要将一些语句编译或放弃很方便

调试性的代码,删除可惜,保留碍事,可以选择性的编译

#include<stdio.h>
#define _DUBUG_
int main()
{
int arr[10]={0};
for(int i=0;i<10;i++)
{
arr[i]=i;
#ifdef _DEBUG_
printf("%d",arr[i]);//为了观察数组是否赋值成功
#endif  //_DEBUG_
}
return 0;
}
1.#if   常量表达式  //条件,常量表达式由预处理器求值#endif
如
#define _DEBUG_ 1
#if _DEBUG_#endif
2.多个分支的条件编译
#if  常量表达式#elif 常量表达式#else#endif3.判断是否被定义
#if defined(symbol)//#ifdef symbol#if !defined(symbol)//#ifndef symbol4.嵌套指令
#if defined(OS_UNIX)#ifdef OPTION1unix_version_option1();#endif#ifdef OPTION2unix_version_option2();#endif
#elif defined(OS_UNIX)#ifdef OPTION2msdos_version_option2();#endif
#endif

12.头文件的包含

本地文件包含

#include"filename"Linux环境标准头文件的路径
/usr/include
VS环境标准头文件的路径2013
C:\program Files (x86)\Microsoft Visual Studio 12.0\VC\include

先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件

库文件包含

#include<filename>

查找头文件直接去标准路径下去查找,找不到就显示编译错误

用""包含也可以,查找的效率会小,不容易区分·

嵌套文件包含#include指令可以使另外一个文件被编译,就像它实际出现于#include指令的地方一样

test.h
void test();test.c
#include<test.h>
#include<test.h>
int main()
{
return 0;
}

这种替换的方式就是预处理器先删除这条指令,并用包含文件的内容替换。如果头文件被重复包含,会被重复编译,对编译的压力比较大

为了解决头文件被重复引入的问题,可以用条件编译,每个头文件的开头写:

#ifndef _TEST_H_
#define _TEST_H_
头文件内容
#endif或者#pragma once

(推荐《高质量C/C++编程指南》的附录考试试卷

停停停!!!!!咕咕咕要考考你!!!!咕咕咕咕咕咕咕咕咕咕咕咕咕咕咕咕咕咕!!!!!

(1) 头文件中ifndef/define/endif干什么的?

  • 防止头文件被重复包含,避免出现重复定义的问题。
  • 确保头文件在整个编译过程中只被包含一次。
  • 这是 C/C++ 编程中的一种标准做法,能够有效解决大型项目里复杂的头文件包含问题。

(2)#include<filename>与#include"filename"的区别

 

特性	       #include <filename>	          #include "filename"
搜索路径优先级	系统标准库目录	          当前源文件目录 → 系统标准库目录
常见用途	     包含系统 / 第三方库头文件   	     包含项目内部自定义头文件
文件位置示例	  /usr/include/stdio.h	     ./my_header.h 或 ./utils/...
编译效率	      可能更快(直接搜索系统目录)	       可能稍慢(先搜索当前目录)

13.其他预处理指令

#error
在预处理阶段生成自定义错误信息,强制编译过程终止。
常用于条件编译中检查不合法的配置或依赖,防止错误代码被编译。
#progma类似上面的防止重复
提供编译器特定的指令,控制编译过程的细节行为。
与标准 C/C++ 语法不同,#pragma是编译器扩展,不同编译器的实现可能不同
#line
重新设置编译器的行号和文件名信息,主要用于调试和自动生成代码的场景。
当编译器报告错误或警告时,会使用#line指定的行号和文件名,
而非实际源代码的行号和文件名。
#progma pack()
控制结构体、联合体的内存对齐方式,影响成员变量在内存中的布局。
默认情况下,编译器会对结构体成员进行对齐(如 4 字节、8 字节对齐),
以提高内存访问效率,但可能导致内存浪费。#pragma pack()可减少这种浪费。

参考《C语言深度解剖》


http://www.hkcw.cn/article/EbKptpsqmB.shtml

相关文章

UI自动化测试的革新,新一代AI工具MidScene.js实测!

前言 AI已经越来越深入地走入我们的实际工作,在软件测试领域,和AI相关的新测试工具、方法也层出不穷。在之前我们介绍过结合 mcp server 实现 AI 驱动测试的案例,本文我们将介绍一个近期崭露头角的国产AI测试工具 Midscene.js Midscene.js简介 MidScene.js 是由字节跳动 w…

什么是CVSD

CVSD&#xff08;Continuous Variable Slope Delta Modulation&#xff0c;连续可变斜率增量调制&#xff09; 是一种用于蓝牙语音通话的超低复杂度音频编码技术。它通过1比特量化实时跟踪音频信号的变化趋势&#xff0c;是早期蓝牙设备&#xff08;HSP/HFP 1.0-1.5&#xff09…

MyBatis动态SQL

还不了解MySQL的可以看我这篇文章&#xff1a; MyBatis入门&#xff1a;快速搭建数据库操作框架 两种增删改查的方法(CRUD)-CSDN博客 动态 SQL 是Mybatis的强⼤特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接 官方文档&#xff1a;动态 SQL_MyBatis中文网 创建相关…

分享智能技能提升6月份排考计划

中级&#xff1a; 6月13号考试 AIGC应用工程师&#xff08;初级&#xff09; 高级&#xff1a; 6月15号考试 人工智能应用工程师&#xff08;高级&#xff09; 大数据分析师&#xff08;高级&#xff09; AIGC应用工程师&#xff08;高级&#xff09; 大数据/数字技术应用工程师…

防火墙ASPF(针对应用层包过滤技术) FTP(主动模式)

1.实验拓扑 2.基础配置 IP地址配置省略 [FW1-policy-security]di th 2025-05-29 12:20:13.740 # security-policy rule name trust->dmz source-zone trust destination-zone dmz source-address 10.1.11.0 mask 255.255.255.0 destination-address 10.1.21.0 ma…

RDS PostgreSQL手动删除副本集群副本的步骤

由于PostgreSQL不支持直接删除副本集群&#xff0c;而是需要先将副本集群升级到主实例(区域集群)&#xff0c;然后在逐一将写入器实例删除&#xff0c;然后才可以删除副本集群 查看现有的主从实例集群 将副本集群提升到区域集群 选择副本集群–>操作–>提升 提升只读副本…

矿用电控系统专用配件铜头铠装4C型护套连接器

矿用电控系统专用配件铜头铠装4C型护套连接器是矿山电气设备中不可或缺的关键组件&#xff0c;其设计、性能与可靠性直接关系到井下作业的安全性和生产效率。随着智能化矿山建设的推进&#xff0c;对连接器的技术要求日益提高&#xff0c;铜头铠装4C型护套连接器凭借其独特的结…

【二】9.关于pinctrl和gpio子系统

前言&#xff1a; 为什么要有pinctrl和gpio子系统呢&#xff1f;--->>>因为LZ不在想推着凯迪拉克其上班了。 1.pinctrl子系统&#xff1a; 因为 ST 针对 STM32MP1 提供的 Linux 系统中&#xff0c;其 pinctrl 配置的电气属性只能在platform 平台下被引用&#xff0c;…

能源领域新兴技术论坛:EMQ 实时数据引擎构建工业智能中枢

5 月 26 日&#xff0c;由沙特阿美亚洲公司主办的能源领域新兴技术论坛在上海顺利举行。本次论坛聚焦智能工厂、无人机与机器人、可靠性与完整性、先进材料四大技术赛道&#xff0c;吸引了来自全球的能源企业、技术供应商及行业专家。 作为业内知名的 MQ AI 实时数据与智能产…

NC52 有效括号序列【牛客网】

文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 NC52 有效括号序列 一、题目描述 二、测试用例 三、解题思路 基本思路&#xff1a;   使用栈进行括号匹配具体思路&#xff1a; 构建括号和数字映射&#xff0c;这样后面就不用写一堆…

Sqlalchemy 连mssql坑

连接失败: (pyodbc.OperationalError) (08001, [08001] [Microsoft][ODBC Driver 17 for SQL Server]SSL Provider: [error:0A00014D:SSL routines::legacy sigalg disallowed or unsupported] (-1) (SQLDriverConnect)) (Background on this error at: https://sqlalche.me/e/…

乾元通渠道商中标青海省自然灾害应急能力提升工程基层防灾项目

近日&#xff0c;乾元通渠道商中标青海省自然灾害应急能力提升工程基层防灾项目&#xff0c;乾元通作为设备厂家&#xff0c;为项目提供通信指挥类装备&#xff08;多链路聚合设备&#xff09;QYT-X1。 青岛乾元通数码科技有限公司作为国家应急产业企业&#xff0c;深耕于数据调…

记一次edu未授权访问漏洞

首先进入该网址是一个登录界面&#xff0c;查看源代码&#xff0c;找到js文件&#xff0c;发现存在js.map前端信息泄露&#xff0c;于是我们进行js还原。 得到前端的一些源代码&#xff0c;以及路由API等&#xff0c;我们就可以通过这个源代码&#xff0c;进行目录遍历&#xf…

Python----目标检测(《用于精确目标检测和语义分割的丰富特征层次结构》和R-CNN)

一、《用于精确目标检测和语义分割的丰富特征层次结构》 1.1、基本信息 原文标题&#xff1a;Rich feature hierarchies for accurate object detection and semantic segmentation 中文译名&#xff1a;用于精确目标检测与语义分割的丰富特征层次结构 版本&#xff1a;第5版技…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Split Landing Page(拆分展示页)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— SplitLandingPage 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ 在这篇文章中&#xff0c;我们将实现一个交互式的左右面板…

Dif-Fusion:第一个基于扩散模型实现的红外光与可见光图像融合的论文

1. 论文介绍 论文主要创新点&#xff1a;提出了第一个基于扩散模型 (Diffusion) 实现的红外光与可见光图像融合模型&#xff0c;但模型不止简单的依赖于 Diffusion&#xff0c;而是一个新颖的 two-stage 的图像融合模型。 Dif-Fusion 利用扩散模型的生成能力&#xff0c;直接在…

Java开发经验——阿里巴巴编码规范实践解析5

摘要 这篇文章主要介绍了阿里巴巴Java开发规范中关于安全和性能优化的实践解析。内容涵盖了配置文件密码加密、用户输入内容风控、SQL注入防护、参数有效性验证、XSS攻击防护、CSRF安全验证、文件上传安全检查、防重放机制等多个方面&#xff0c;通过正反示例和推荐做法&#…

如何在python3.8环境中安装pytorch

我的conda配置了两个独立环境&#xff1a; base环境 - 安装有Python 3.12及各类依赖包&#xff1b;pytorch环境 - 基于Python 3.8创建&#xff0c;包含特定功能包。 在Anaconda Prompt中激活您的PyTorch环境&#xff1a; 访问PyTorch官网历史版本页面&#xff08;https://pyt…

源的企业级网络安全检测工具Prism X(棱镜X)

Prism X&#xff08;棱镜X&#xff09;是由yqcs团队自主研发的开源网络安全检测解决方案&#xff0c;专注于企业级风险自动化识别与漏洞智能探测。该工具采用轻量化架构与跨平台设计&#xff0c;全面兼容Windows、Linux及macOS操作系统&#xff0c;集成资产发现、指纹鉴别、弱口…

ADB识别手机系统弹授权框包含某段文字-并自动点击确定按钮

ADB识别手机系统弹授权框包含某段文字-并自动点击确定按钮 --蓝牙电话App自动部署 上一篇&#xff1a;手机打电话时将对方DTMF数字转为RFC2833发给局域网SIP坐席 下一篇&#xff1a;编写中。 一、前言 蓝牙电话方案中&#xff0c;我们提供了将手机通话的语音拦截后转发到局域…