大话C语言:第24篇 预处理
1 C语言编译流程
C语言的编译流程包括:
-
预编译:将.c 中的头文件展开、宏展开,生成的文件是.i 文件。gcc指令:gcc -E file.c -o file.i
-
编译:将预处理之后的.i 文件生成 .s 汇编文件。gcc指令:gcc -S file.i –o file.s
-
汇编:将.s 汇编文件生成.o 目标文件。gcc指令:gcc -c file.s -o file.o
-
链接:将.o 文件链接成目标文件。gcc -o file file.o

2 #include
-
#include<>//用尖括号包含头文件,在系统指定的路径下找头文件
-
#include "" //用双引号包含头文件,先在当前目录下找头文件,找不到,再到系统指定的路径下找。
注意:预处理只是对 include 等预处理操作进行处理并不会进行语法检查;这个阶段有语法错误也不会报错,编译阶段才进行语法检查。
3 #define
#define是用来定义宏,宏是在预编译的时候进行替换。#define包括:
3.1 不带参宏
语法格式:
#define 宏名 常量
例如,定义圆周率,#define PI 3.14,在预编译的时候如果代码中出现了 PI 就用 3.14 去替换。
#include <stdio.h>#define PI 3.14int main()
{printf("%lf\n",PI);return 0;
}
注意,
-
只要修改宏定义,其他地方在预编译的时候就会重新替换。
-
宏定义后边不要加分号。
-
宏定义的作用范围,从定义的地方到本文件末尾。
如果想在中间终止宏的定义范围,可以使用#undef。例如,终止刚定义的PI,#undef PI
#include <stdio.h>#define PI 3.14int main()
{printf("%lf\n",PI);#undef PI#define PI 3.1415printf("%lf\n",PI);return 0;
}
3.2 带参宏
语法格式:
// 表达式是由参数1至参数n构成
#define 宏名(参数1,参数2,...,参数n) 表达式
例如,两数相乘,#define Sum(num1, num2) num1*num2
#include <stdio.h>#define Sum(num1, num2) num1*num2int main(int argc, char *argv[])
{int result = Sum(10,20);printf("result=%d\n", result);return 0;
}
实际上,带参数的宏只做简单的参数替换,上述案例中,Sum(10,20),本质上,10*20;如果我们传入的Sum(10+6, 20)的话,宏展开后,10+6 * 20。
#include <stdio.h>#define Sum(num1, num2) num1*num2int main(int argc, char *argv[])
{int result = Sum(10+6, 20);printf("result=%d\n", result);return 0;
}
要解决上述问题,最好的办法就是对每个参数单独使用(),改进一下上述代码
#include <stdio.h>#define Sum(num1, num2) (num1) * (num2)int main(int argc, char *argv[])
{int result = Sum(10+6, 20);printf("result=%d\n", result);return 0;
}
注意,带参宏被调用多少次就会展开多少次,执行代码的时候没有函数调用的过程,不需要压栈弹栈。所以带参宏,是浪费了空间,因为被展开多次,节省时间。
4 选择性编译
选择性编译是指在编译过程中,根据特定的条件或环境的不同,选择性地让特定的代码语句有效或无效。这种编译方式允许开发者在不同的环境或配置下编译不同的代码,以实现灵活的程序控制和功能切换。
在C语言中,选择性编译通常通过预处理器指令来实现,如#ifdef、#ifndef、#else和#endif等。这些指令可以在预处理阶段根据是否定义了某个宏,来决定是否编译特定的代码段。例如,在开发环境中可能需要打印调试信息,而在生产环境中则不需要,通过选择性编译可以在生产环境中排除这些打印语句,以提高程序的运行效率。
选择性编译的主要作用是防止头文件重复定义和代码编译冗余,从而确保程序的正确性和效率。同时,它也使程序更加灵活和可配置,可以根据不同的需求和环境进行定制。
4.1 #ifdef
语法格式:
#ifdef XXX// 功能代码1
#else// 功能代码2
#endif
如果已经定义过 XXX(建议取有意义名字) ,就编译功能代码1,否则编译功能代码1。
#include <stdio.h>#define LANGint main(int argc, char *argv[])
{#ifdef LANGprintf("hello world!!\n");#elseprintf("世界,你好!\n");#endifreturn 0;
}
4.2 #ifndef
语法格式:
#ifndef XXX// 功能代码1
#else// 功能代码2
#endif
这种方式是和第一种互补,例如
#include <stdio.h>// #define LANGint main(int argc, char *argv[])
{#ifdef LANGprintf("hello world!!\n");#elseprintf("世界,你好!\n");#endifreturn 0;
}
4.3 #if
语法格式:
#if 表达式// 功能代码1
#else// 功能代码2
#endif
如果表达式为真,编译功能代码1,否则编译功能代码2。例如
#define DEBUG 1 int main()
{
#if DEBUG // 功能代码1: 调试用的代码 printf("调试代码.\n");
#else // 功能代码2: 不包含调试的代码 printf("关闭调试代码.\n");
#endif return 0;
}
注意,如果DEBUG定义为0,表达式为假(false),执行#else。
相关文章:
大话C语言:第24篇 预处理
1 C语言编译流程 C语言的编译流程包括: 预编译:将.c 中的头文件展开、宏展开,生成的文件是.i 文件。gcc指令:gcc -E file.c -o file.i 编译:将预处理之后的.i 文件生成 .s 汇编文件。gcc指令:gcc -S file…...
React如何配置路由
ReactTs配置路由 安装依赖 npm i react-router-dom在routers下面创建index.tsx import { RouteObject } from react-router-dom import React from react import PageA from /views/PageA import PageB from /views/PageB const routes: RouteObject[] [{path: /,element: …...
MAC使用初体验+入门
之前从来没有使用过MAC,这次拿到了一个 不得不说MAC度过适应期后用起来很舒服,续航长,触控板舒服,轻薄无比 我前期过度的时候记录的一部分快速指南,掌握如下一些电脑常识 可以做到正常使用了 基本操作 在 Mac 上使用桌…...
Go TOKEN机制与跨域处理方式
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
JavaScript 的运行
语法分析预编译解释执行 1.语法分析 语法分析是 JavaScript 引擎处理代码的第一步。 在这个阶段,引擎将源代码字符串分解成一个个的词素(token),这些词素是语言中有意义的最小单元,如关键字、变量名、操作符等。 语…...
园区地图导航系统:技术原理、部署方案与智能化应用解析
随着智能化时代的到来,园区管理面临诸多挑战。维小帮园区地图导航系统,采用前沿技术,为园区提供全面的导航解决方案,极大提升了园区管理效率和用户体验。 一、园区地图导航系统的功能特点 维小帮园区地图导航系统,以其…...
【数据结构】第十六弹---C语言实现希尔排序
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1、希尔排序( 缩小增量排序 ) 1.1、预排序实现 1.2、希尔排序代码实现 1.3、代码测试 1.4、时空复杂度分析 1.5、性能比较 总结 上一弹我们…...
用Python向Word文档添加页眉和页脚
用Python向Word文档添加页眉和页脚 添加页眉和页脚效果代码 添加页眉和页脚 在本文中,我们将用python向文档中添加页眉和页脚。 效果 添加前的文档: 添加页眉和页脚后: 代码 from docx import Documentdef add_header_footer(doc_path…...
REST风格
黑马程序员Spring Boot2 文章目录 1、REST简介1.1 优点1.2 REST风格简介1.3 注意事项 2、RESTful入门案例 1、REST简介 1.1 优点 隐藏资源的访问行为,无法通过地址的值对资源适合中操作书写简化 1.2 REST风格简介 按照RST风格访问资源时使用行为动作区分对资源进…...
Mongodb连接测试程序【Java版】
先导入Maven依赖 <dependency><groupId>org.mongodb</groupId><artifactId>mongodb-driver-sync</artifactId><version>4.9.0</version> </dependency>import com.mongodb.MongoClientSettings; import com.mongodb.MongoCred…...
SM3国密算法:优秀的密码散列函数
随着信息技术的飞速发展,信息安全已成为全球关注的焦点。密码学作为保障信息安全的核心技术,其重要性不言而喻。中国在密码学领域也取得了显著的成就,其中SM3国密算法就是中国自主设计并推广使用的密码学标准之一。 一、SM3算法概述 SM3算法…...
【安卓】在安卓中使用HTTP协议的最佳实践
人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…...
Spring Boot集成antlr实现词法和语法分析
1.什么是antlr? Antlr4 是一款强大的语法生成器工具,可用于读取、处理、执行和翻译结构化的文本或二进制文件。基本上是当前 Java 语言中使用最为广泛的语法生成器工具。Twitter搜索使用ANTLR进行语法分析,每天处理超过20亿次查询࿱…...
多线程中run()和start()的区别
我们知道,在多线程中 Thread thread new Thread(runnable); thread.start();以及 thread.run();都可以执行runnable中run方法下的代码,但是二者又有所不同 下面给出一段代码用以体现二者的区别: 以下代码中,通过thread.start()启…...
Nginx基础理论
Nginx最为最受欢迎的反向代理和负载均衡服务器,被广泛的应用于互联网项目中。这不仅仅是因为Nginx本身比较轻量,更多的是得益于Nginx的高性能特性,以及支持插件化开发,为此,很多开发者或者公司基于Nginx开发出了众多的…...
【QT5】<应用> 小游戏:贪吃蛇
文章目录 一、项目要求 二、需求分析 三、实现效果 四、代码 一、项目要求 【1】主要实现:游戏界面存在一条蛇🐍,使用键盘wsad或者↑↓←→键盘可以控制蛇的行走方向。同时界面中会随机出现食物,蛇可以吃食物,然后…...
【Webpack】使用 Webpack 构建 Vue3+TS 项目
构建项目目录 tsc --init npm init -yshim.d.ts 文件是一个类型声明文件,用于告诉 TypeScript 编译器如何处理 Vue 的单文件组件(SFC)和其他自定义模块。为 Vue 的单文件组件和其他非 TypeScript 模块提供类型信息,以便在 TypeScr…...
数据防泄漏的六个步骤|数据防泄漏软件有哪些
在当前复杂多变的网络安全环境下,数据防泄漏软件成为了企业信息安全架构中不可或缺的一环。下面以安企神软件为例,告诉你怎么防止数据泄露,以及好用的防泄露软件。 1. 安企神软件 安企神软件是当前市场上备受推崇的企业级数据防泄漏解决方案…...
SpringCloud 网关Gateway配置并使用
目录 1 什么是网关? 2 Gateway的使用 2.1 在其pom文件中引入依赖 2.2 然后gateway配置文件中配置信息 2.3 启动网关微服务 3 网关处理流程 4 前端-网关-微服务-微服务间实现信息共享传递 1 什么是网关? 网关:就是网络的关口ÿ…...
MySQl基础----Linux下搭建mysql软件及登录和基本使用(附实操图超简单一看就会)
绪论 涓滴之水可磨损大石,不是由于他力量强大,而是由于昼夜不舍地滴坠。 只有勤奋不懈地努力,才能够获得那些技巧。 ——贝多芬。新开MySQL篇章,本章非常基础包括如何在Linux上搭建(当然上面的SQL语句你在其他能执行…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
