【C语言】预处理器
我们在开始编写一份程序的时候,从键盘录入的第一行代码:
#include <stdio.h>
这里就使用了预处理,引入头文件。
C预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。
预处理指令
| 指令 | 描述 |
|---|---|
| #define | 定义宏 |
| #include | 包含一个源代码文件 |
| #undef | 取消已定义的宏 |
| #ifdef | 如果宏已经定义,则返回真 |
| #ifndef | 如果宏没有定义,则返回真 |
| #if | 如果给定条件为真,则编译下面代码 |
| #else | #if 的替代方案 |
| #elif | 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码 |
| #endif | 结束一个 #if……#else 条件编译块 |
| #error | 当遇到标准错误时,输出错误消息 |
| #pragma | 使用标准化方法,向编译器发布特殊的命令到编译器中 |
示例:
#define MAX_ARRAY_LENGTH 20
这个指令告诉 CPP 把所有的 MAX_ARRAY_LENGTH 定义为 20。使用 #define 定义常量来增强可读性。
#include <stdio.h>
#include "myheader.h"
这些指令告诉 CPP 从系统库中获取 stdio.h,并添加文本到当前的源文件中。下一行告诉 CPP 从本地目录中获取 myheader.h,并添加内容到当前的源文件中。
#include < > 引用的是编译器的类库路径里面的头文件。
#include " " 引用的是你程序目录的相对路径中的头文件,如果在程序目录没有找到引用的头文件则到编译器的类库路径的目录下找该头文件。
在有多个 .h 文件和多个 .c 文件的时候,往往我们会用一个 global.h 的头文件来包括所有的 .h 文件,然后在除 global.h 文件外的头文件中 包含 global.h 就可以实现所有头文件的包含,同时不会乱。方便在各个文件里面调用其他文件的函数或者变量。
#ifndef _GLOBAL_H
#define _GLOBAL_H
#include <fstream>
#include <iostream>
#include <math.h>
#include <Config.h>
C语言代码的头文件与源文件有什么区别?
#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,您可以在编译期间随时开启或关闭调试。
#error命令是C/C++语言的预处理命令之一,当预处理器预处理到#error命令时将停止编译并输出用户自定义的错误消息。如下所示:
#include <stdio.h>
#define SHOW_INFO
int main(void)
{
#ifndef SHOW_INFO#error you must define SHOW_INFO marco.
#endifprintf("hello world!\n");return 0;
}
当删去"#define SHOW_INFO"语句就会输出错误消息
#pragma的常用方法讲解
预定义宏
ANSI C 定义了许多宏。在编程中您可以使用这些宏,但是不能直接修改这些预定义的宏。
| 宏 | 描述 |
|---|---|
| __DATE__ | 当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。 |
| __TIME__ | 当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。 |
| __FILE__ | 这会包含当前文件名,一个字符串常量。 |
| __LINE__ | 这会包含当前行号,一个十进制常量。 |
| __STDC__ | 当编译器以 ANSI 标准编译时,则定义为 1。 |
实例:
#include <stdio.h>
int 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__ );return 0;
}
预处理器运算符
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()
{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()
{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!"
#endif
int main()
{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
Reference:
C 预处理器 | 菜鸟教程 (runoob.com)
相关文章:
【C语言】预处理器
我们在开始编写一份程序的时候,从键盘录入的第一行代码: #include <stdio.h>这里就使用了预处理,引入头文件。 C预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C预处理器只不过是一…...
QtConcurrent::run操作界面ui的注意事项(2)
前面的“QtConcurrent::run操作界面ui的注意事项(1)”,末尾说了跨线程的问题,引出了Qt千好万好,就是跨线程不好。下面是认为的最简单的解决办法:使用QMetaObject::invokeMethod(相比较信号-槽&a…...
黑马程序员HarmonyOS4+NEXT星河版入门到企业级实战教程笔记
HarmonyOS NEXT是纯血鸿蒙,鸿蒙原生应用,彻底摆脱安卓 本课程是基于harmony os4的,与next仅部分api有区别 套件 语言&框架 harmony os design ArkTs 语言 ArkUI 提供各种组件 ArkCompiler 方舟编译器 开发&测试 DevEco Studio 开发…...
嵌入式全栈开发学习笔记---C语言笔试复习大全13(编程题9~16)
目录 9.查找字符数组中字符位置(输入hello e 输出2); 10、查找字符数组中字符串的位置(输入hello ll 输出3); 11、字符数组中在指定位置插入字符;(输入hello 3 a 输出heallo…...
https网站安全证书的作用与免费申请办法
HTTPS网站安全证书,也称为SSL证书,网站通过申请SSL证书将http协议升级到https协议 HTTPS网站安全证书的作用 1 增强用户信任:未使用https协议的网站,用户访问时浏览器会有“不安全”弹窗提示 2 提升SEO排名:搜索引擎…...
自动化测试再升级,大模型与软件测试相结合
近年来,软件行业一直在迅速发展,为了保证软件质量和提高效率,软件测试领域也在不断演进。如今,大模型技术的崛起为软件测试带来了前所未有的智能化浪潮。 软件测试一直是确保软件质量的关键环节,但传统的手动测试方法存…...
centos7 基础命令
一、基础信息: 查看IP地址: ip add 重启网络服务: service network restart 查看网卡配置: cat /etc/sysconfig/network-scripts/ifcfg-ens33 启动网卡: ifup ens33 查看内存: free -m 查看CPU: cat /proc/cpuin…...
【设计模式】之单例模式
系列文章目录 【设计模式】之责任链模式【设计模式】之策略模式【设计模式】之模板方法模式 文章目录 系列文章目录 前言 一、什么是单例模式 二、如何使用单例模式 1.单线程使用 2.多线程使用(一) 3.多线程使用(二) 4.多线程使用…...
3d模型实体显示有隐藏黑线?---模大狮模型网
在3D建模和设计领域,细节决定成败。然而,在处理3D模型时,可能会遇到模型实体上出现隐藏黑线的问题。这些黑线可能影响模型的视觉质量和呈现效果。因此,了解并解决这些隐藏黑线的问题至关重要。本文将探讨隐藏黑线出现的原因&#…...
共享购:全新消费模式的探索与实践
在消费模式日益创新的今天,共享购模式以其独特的消费与收益双重机制,吸引了众多消费者的目光。这一模式不仅为消费者带来了全新的购物体验,也为商家和平台带来了可观的收益。 一、会员体系:共享购的基石 在共享购模式下ÿ…...
Java集合 总结篇(全)
Java集合 集合底层框架总结 List 代表的有序,可重复的集合。 ArrayList -- 数组 -- 把他想象成C中的Vector就可以,当数组空间不够的时候,会自动扩容。 -- 线程不安全 LinkedList -- 双向链表 -- 可以将他理解成一个链表,不支持…...
Dubbo分层架构深度解析
引言 Dubbo作为一款备受欢迎的高性能、轻量级的Java RPC框架,在现代分布式系统中扮演着至关重要的角色。随着互联网行业的快速发展,服务间的通信变得越来越频繁,这也使得对于高效、可靠的远程通信方案的需求变得愈发迫切。在这样的背景下&am…...
LocalDate 数据库不兼容问题,因为LocalDate 是 long 类型的
我今天遇到一报错: SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession316f9272] was not registered for synchronization because synchronization is not active JDBC Connection [HikariProxyConnection2127597288 wrapping com.mysql.cj.jdbc…...
RVM(相关向量机)、CNN_RVM(卷积神经网络结合相关向量机)、RVM-Adaboost(相关向量机结合Adaboost)
当我们谈到RVM(Relevance Vector Machine,相关向量机)、CNN_RVM(卷积神经网络结合相关向量机)以及RVM-Adaboost(相关向量机结合AdaBoost算法)时,每种模型都有其独特的原理和结构。以…...
Java--方法的使用
1.1什么是方法 方法顾名思义就是解决问题的办法,在程序员写代码的时候,会遇到很多逻辑结构一样,解决相同问题时,每次都写一样的代码,这会使代码看起来比较绒余,代码量也比较多,为了解决这个问题…...
linux - 主次设备号自动申请
alloc_chrdev_region 原型如下,该函数向内核申请一个空闲的主设备号。 alloc_chrdev_region(&g_aputriger_dev, 0, APUTRIGER_MAX_NUM, "aputriger0"); 第四个参数是我们使用cat /proc/devices 看到的名称 /*** alloc_chrdev_region() - register a…...
我写了一套几乎无敌的参数校验组件!基于 SpEL 的参数校验组件「SpEL Validator」
前言 大家好,我是阿杆,不是阿轩。 参数校验这个东西,很多情况下都是比较简单的,用 NotNull、Size 等注解就可以解决绝大多数场景,但也有一些场景是这些基本注解解决不了的,只能用一些其他的方式处理&…...
输入序列太长 gan CGAN
transformer序列长度大导致计算复杂度高 GAN 2. 训练过程 第一阶段:固定「判别器D」,训练「生成器G」。使用一个性能不错的判别器,G不断生成“假数据”,然后给这个D去判断。开始时候,G还很弱,所以很容易被…...
uni-app scroll-view隐藏滚动条的小细节 兼容主流浏览器
开端 想写个横向滚动的列表适配浏览器,主要就是隐藏一下滚动条在手机上美观一点。 但是使用uni-app官方文档建议的::-webkit-scrollbar在目标标签时发现没生效。 .scroll-view_H::-webkit-scrollbar{display: none; }解决 F12看了一下,原来编译到浏览…...
Java常用API之LinkedList类解读
写在开头:本文用于作者学习我将官方文档中LinkedList 1.6版本中类中绝大部分API全测了一遍并打印了结果,日拱一卒,常看常新。 自己补充了一些对该数据结构的理解,如有不对的地方,请各位指正,谢谢。 首先&…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
