C硬核:聊聊预编译指令和宏的应用场景(一)

C/C++静态库封装实战:从原理到工程实践 在软件工程中,代码封装与模块化是构建可维护、可复用系统的核心原则。其基本原理在于通过接口与实现的分离,隐藏内部细节,对外提供稳定、清晰的契约。这一技术价值不仅体现在提升代码安全性和知识产权保护上,还能有效简化项目结构、加速编译过程,并强制良好的架构设计。在实际应用场景中,当需要将核心算法、业务逻辑或基础组件以二进制形式分发给客户、合作伙伴或跨项目集成时,静态库(Static Library)便成为一种经典且高效的解决方案。它通过将源代码预编译为目标文件并打包,使核心实现安全地“溶解”在最终的可执行文件中,避 阅读详情

C语言硬件编程栏目

往期文章:工作数年还是被指针坑了——谈谈C语言指针运算



前言

C语言编程中离不开预编译指令,编译器在预编译阶段,会根据预编译指令对你编写的代码进行处理。
例如,我们在写第一段C程序"HelloWorld"的时候,就用到了#include指令来包含stdio.h这样的头文件了;
而用于定义宏名称的指令#define也属于预编译指令,而且也是用的最多的预编译指令。
下面我们就围绕预编译指令和宏的应用场景,看看哪些是容易被忽略的预编译指令以及重要的应用场景。


一、预编译指令

C中的预编译指令很多,包括#define,#undef,#if,#ifdef,#ifndef,#error,#line, #pragma等等,常用且重要的指令主要是如下这些:

#define指令

编程中最常用的预编译指令要属#define宏定义指令了,其用法及形式如下:

#define NAME stuff

这样在code中其他使用NAME宏名的地方,都会被替换为stuff,这里的stuff可以是各种文本;最常见的常量数值,例如

#define PI 3.1415926

如果要移除一个前面定义的宏,用#undef即可。

#if指令

#if指令用于编译过程的分支判断,和#elif/#else/#endif配合使用。其形式如下:

#if Constant-Expression
  statements
#elif Constant-Expression2
  statements2
#else
  statements3
#endif

因为在Constant-Expression域内可以填写各种表达式的组合,所以该指令往往使用起来灵活多变。例如和defined/!defined配合使用,从而限定某个条件下编译的code,该用法也是常常不被重视但颇有用的一种:

#if defined(MACRO_A) && !defined(MACRO_B)
  statements
#endif

这样只有在定义MACRO_A和未定义MACRO_B的时候,才会执行如下的statements。

#ifdef指令

#ifdef指令和#if defined指令是等价的,所以常用#ifdef和#ifndef来实现宏定义下或非定义宏的条件下对code的执行,使用起来简单,但是没次只能对一个宏进行判断,不如#if指令灵活。

#include指令

该指令用于包含code中所需要的头文件,需要注意的是,包含的形式有两种:

//first one
#include <Library/file.h>
//second one
#include "file.h"

两者在检索头文件的过程中,是完全不一样的。第一种会按照编译器指定的库文件目录为根,向下检索头文件;而第二种则会按照当前编辑的C文件为根,去检索file.h。因此我们在使用的时候,如果头文件位于当前目录下,使用第2种方式最佳。

#pragma指令

一定注意,该指令名称是#pragma,不是#progma!
该指令稍显复杂,用于设定编译器的状态,指示编译器完成特定的动作。经常配合使用的参数包括message,warning和pack。而我们最常用和最重要的,就是和pack的搭配使用了。使用形式如下:

#pragma pack(n)

在默认情况下,对于结构体是按照最节省空间的方式进行对齐的,如下面的TestStruct1按照最大长度的int i进行对齐,c1/s/c2整体拼成一个单元,如表中所示,即按照pack(1)一个字节进行对齐:

struct TestStruct1
{
   char c1;
   short s;
   char c2;
   int i;
};

内存分布表
内存分布表

当然,上述默认的方式不一定适合编程时数据的访问,如果统一按照4个字节int类型进行访问,那么在结构体声明时使用pack(4)即可,那么这里的内存分布会变成:

c1
s
c2
i

取消自行设定的对齐方式,再使用#pragma pack()即可。下次我们以UEFI kernel为模板,再聊聊宏的应用场景~

宝塔面板下Nginx集成GeoIP2模块实战指南 本文详细介绍了在宝塔面板环境下,为Nginx手动编译并集成GeoIP2模块的完整实战指南。通过步骤解析,帮助用户实现基于IP地址识别访客地理位置的功能,从而轻松实现网站内容地域限制、差异化展示或流量屏蔽,提升运维效率与安全性。 阅读详情

相关推荐

Python项目内网迁移实战:依赖打包与离线部署指南

本文详细介绍了Python项目在内网环境中的完整迁移与部署流程。针对无法连接外网的情况,提供了从外网精准生成依赖清单、下载离线依赖包,到内网创建虚拟环境、离线安装依赖的实战指南。文章还探讨了搭建私有PyPI仓库等进阶方案,并分享了关键的避坑经验,帮助开发者高效、可靠地完成项目内网部署。

ee345的博客 358

c 宏的常用场景应用举例

c 宏的常用场景应用举例

xie__jin__cheng的博客 837

1 宏的使用大全

宏,也叫宏定义,并不是C/C++语言本身的一部分,不能直接对宏进行编译。在编译程序前,必须先对宏进行预先的处理(专业术语叫作“预处理”)。预处理器会分析所有的源文件,当遇到宏名称严格匹配时,就会展开宏,也就是用定义好的文本来代替宏名称。宏的用途主要有三点:一是可以为程序员的开发提供一定的便利性;二是可以有效减少源文件中大量重复的、相似的代码;三是可以在一定程度上减少系统的开销,提高程序的运行效率。C/C++语言预定义了一些宏定义,常用的宏定义如下表。宏名称数据类型备注__FILE__字符串。

hope_wisdom的技术博客 3570

宏的常见应用领域

1,跨平台,通过宏可以编译相应操作系统的api 2,定制业务,同一份代码,面向不同的客户,通过宏来定制。 3,Release 和 Debug。在release下,不能崩的,在debug下,是希望尽早暴露问题的。

wusoule的专栏 1257

海康VisionMaster使用学习笔记7-Group模块

光标需放在[]中选择循环索引,循环索引用于实现依次检测10个匹配框的顶点,若不订阅,模块会循环检测同一个匹配框。可以看到绿色是它的边缘点.为方便查看顶点,将边缘点设置为不可见。循环使能打开,开始值设为0,循环结束值设为快速匹配的匹配个数。回到上一层,点击Group工具的设置图标,圆拟合的点设置为Group工具输出的点集。图像输入源选择Group的图像输入源。区域选择Group的快速匹配的匹配框。添加订阅到Group内部的顶点检测。对匹配框区域进行顶点检测。用于定位匹配框中的顶点。添加快速匹配的匹配框。

风凌的博客 4175

实战指南:将MediaPipe封装为Windows DLL,实现C++/C#高效调用

在计算机视觉和多媒体处理领域,跨平台框架为开发者提供了强大的算法模型和计算能力。其核心原理在于通过预训练的机器学习模型和优化的计算图,实现对图像、视频流中特定目标(如人脸、手势、姿态)的实时检测与分析。这项技术的价值在于能够将复杂的AI能力模块化,降低应用开发门槛。在实际工程实践中,为了突破特定语言生态的限制并优化部署流程,开发者常需将核心功能封装成独立的库。例如,将Google的MediaPipe框架封装为Windows动态链接库(DLL),就是一个典型的工程实践。此举能有效解决语言壁垒和部署简化问题,使

weixin_28691741的博客 360

单片机数组前的code的作用

目录code的作用 RAMROMRAM和ROM相比节约RAM空间的作用没用code 时,数组定义在RAM里面,有code时,数组定义在ROM里面(固定的数据,不能修改) RAM又被称作“随机存储器”,是与CPU直接交换数据的内部存储器,也叫主存(内存)。它可以随时读写,而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介。当电源关闭时RAM不能保留数据(掉电数据消失哦)如果需要保存数据,就必须把它们写入一个长期的存储设备中(例如硬盘)。 ROM又被称为“只读存储器”,ROM所存数据,一般

公众号:风景邮递Yuan的博客 1827

maya权重拷贝一对一,一对多

是不是有时候盔甲很多很碎头很大,用代理一个个拷贝很麻烦吧 用下面代码直接运行进行一对多或者一对一拷贝 第一个先选择参考物体,加选其他一堆有的没的有权重或没权重的物体执行一键拷贝,就可以啦 以下是源码送上,带走吧 ------------------------ #! -*- coding:utf -8 -*- #author:liubingdong #date:20...

weixin_30852367的博客 1532

C硬核:聊聊预编译指令和宏的应用场景(二)

C语言硬件编程栏目 往期文章: 工作数年还是被指针坑了——谈谈C语言指针运算 C硬核:聊聊预编译指令和宏的应用场景(一) C硬核:聊聊预编译指令和宏的应用场景(二)C语言硬件编程栏目前言一、如何方便维护那些值不变的参数?二、如何对你的printf/debug语句分级?1.定义DebugPrintErrorLevel的划分细则2.设计和Error Level相关联的print函数3. 调整宏DebugPrintErrorLevel或入口参数errorlevel三、如何批量替换一系列代码?总结 前言 关

Cerman的博客 836

STC32-USB-CAN:基于STC32G的国产双通道隔离CAN分析调试设备设计与实战

本文详细介绍了基于国产STC32G单片机设计双通道隔离CAN分析调试设备的全过程。该设备实现了双通道隔离CAN数据监控、中继转发及USB高速通信,并支持故障注入测试。核心采用全国产器件,通过实战测试验证了其在1Mbps波特率下长时间稳定工作的可靠性,为工程师提供了高性价比的CAN总线调试解决方案。

weixin_42465140的博客 97

科研党必备:用Python+Excel批量下载文献的保姆级教程(附常见错误解决)

本文提供了一套利用Python和Excel实现外文文献批量下载的自动化解决方案。教程详细介绍了如何从数据库导出并清洗DOI信息,编写健壮的Python脚本进行批量下载,并包含错误处理与进阶优化技巧,旨在帮助科研人员将重复性劳动自动化,大幅提升文献收集效率。

weixin_29050513的博客 306

ESP32C3启动流程揭秘:从复位向量到RTOS调度的关键步骤

本文深入解析了ESP32C3芯片从复位向量到RTOS调度的完整启动流程。详细拆解了ROM一级引导程序、Flash二级引导程序的关键步骤,包括启动模式选择、复位原因处理、分区表解析、安全启动验证等核心环节,并阐述了FreeRTOS调度器如何最终接管系统,为开发者解决启动相关问题和优化系统性能提供清晰指引。

weixin_29185167的博客 264

【扣子AI开发】如何开发一个图像生成智能体?

【扣子AI开发】如何开发一个图像生成智能体,从创建到发布

tl437002770的博客 2427

SenseVoice-Small语音识别入门:C语言调用ONNX Runtime推理引擎教程

本文介绍了如何在星图GPU平台上自动化部署sensevoice-small-语音识别-onnx模型(带量化后),实现高效的本地语音识别应用。通过C语言调用ONNX Runtime推理引擎,开发者可以轻松集成该模型,适用于嵌入式设备或桌面程序的语音转文字场景,如语音指令识别、实时字幕生成等。

weixin_31139479的博客 155

微信电脑版本不会自动下载图片吗?——没有找到解决方法。——只会默认下载doc等文件,图片不行,需要自己另存为——有什么办法解决吗?

微信电脑版本不会自动下载图片吗?——没有找到解决方法。——只会默认下载doc等文件,图片不行,需要自己另存为——有什么办法解决吗?此外,用户还可以选择将接收到的图片、视频和文件保存到指定的文件夹中。‌用户可以在微信设置中调整这一设置。

qq_15963745的博客 5088

VTsystem背景检查函数Value Valid

Value Valid是个非常实用的函数,如何让它灵活的为我们所用,便是本文的内容。

欢迎来到eee的博客 794

云容笔谈·东方红颜影像生成系统C语言基础调用示例:通过C接口实现高性能集成

本文介绍了如何在星图GPU平台上自动化部署💃 云容笔谈 · 东方红颜影像生成系统镜像,并通过C语言接口实现高性能集成。该方案特别适用于对性能有极致要求的场景,例如在嵌入式设备或服务器中直接调用模型进行AI图片生成,从而满足低延迟、高效率的内容创作需求。

weixin_42126677的博客 22

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

李慕婉-仙逆-造相Z-Turbo C语言基础调用示例:轻量级嵌入式集成探索

本文介绍了如何在星图GPU平台上自动化部署李慕婉-仙逆-造相Z-Turbo镜像,并探索了其轻量级C语言调用方案。该方案使资源受限的嵌入式设备能通过网络API调用该AI模型,实现水墨画风格等特定场景的图片生成功能,为边缘AI应用提供了高效集成路径。

weixin_33363025的博客 109

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【硬核排障】Windows 下 Python 报 DLL load failed?从 CPython 编译机制讲透 VC++ 依赖地狱(附 AIO 修复包)

本文深入分析了Windows下Python报DLL加载失败的底层原因,主要涉及CPython解释器与MSVC运行库的依赖关系。文章指出: CPython核心和许多Python扩展库实质是通过C-API封装的DLL文件,依赖MSVCRT运行库 手动下载DLL文件存在架构兼容性和程序集注册问题 提供了DLL依赖链诊断脚本定位缺失文件 推荐使用微软官方VC++ AIO运行库合集进行修复 提供了包含静默安装脚本的完整修复包下载地址 解决方案避免了安装臃肿的Visual Studio,通过官方运行库即可解决DLL加载

ai-codex-python博客 213

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

ARM Cortex-M1 FPGA软核:技术遗产、商业博弈与当代启示

在嵌入式系统与可编程逻辑领域,处理器软核扮演着连接硬件灵活性与成熟软件生态的关键角色。其核心原理在于通过硬件描述语言在FPGA内部构建可定制的计算单元,实现软硬件协同设计。这项技术的价值在于能针对特定应用优化性能与功耗,并复用庞大的现有软件资产。典型的应用场景包括实时控制、信号处理加速和高度定制化的嵌入式系统。ARM Cortex-M1作为一款专为FPGA优化的32位ARM处理器软核,正是这一技术路线的早期重要实践。它基于Cortex-M3架构深度裁剪,支持Thumb-2指令集与紧耦合内存(TCM),旨在将

weixin_30565327的博客 465

为什么从 esptool.py 转向 espflash:Rust 版 ESP32 串口烧录工具的 3 个硬核优势

做嵌入式开发的朋友,大概率都用过 esptool.py 给 ESP32 刷固件。但 Python 环境依赖、烧录后还得自己开串口监视器、无法融入 Rust 工作流——这些痛点,**espflash** 一次全解决了。 espflash 是一款基于 Rust 实现的 **ESP32 串口烧录工具**(Serial flasher utility),功能对标 esptool.py,支持 **ESP3

gitblog_00483的博客 649

嵌入式开发自学指南:从C语言到RTOS与Rust的实战路径

嵌入式开发是计算机系统与物理世界交互的核心技术领域,其本质在于通过微控制器或微处理器执行特定任务,实现对硬件设备的直接控制。其技术原理建立在底层硬件认知、高效的编程语言以及实时操作系统之上,通过直接操作寄存器、管理内存和处理中断来确保系统的可靠性与实时性。这一技术价值在于能够构建高可靠性、低功耗且响应迅速的系统,广泛应用于物联网、汽车电子、工业控制及消费电子等场景。对于初学者而言,掌握以C语言为核心的编程基础、理解ARM Cortex-M系列微控制器架构,并熟练使用如VSCode配合GCC和OpenOCD的

weixin_30482383的博客 529

Python离线开发全攻略:从Whl到Anaconda虚拟环境

本文详细介绍了Python离线开发的两大核心方法:手动处理Whl文件与迁移Anaconda虚拟环境。针对无法联网的开发场景,文章提供了从依赖包递归下载、安装顺序到完整环境打包迁移的实战指南,并分享了搭建本地仓库、依赖清单管理等高级技巧,帮助开发者在封闭环境中高效部署Python项目。

weixin_29063035的博客 221

在 Deepin 20.9 + N卡 930MX(2GB) 上跑 Qwen3.5 模型

折腾日志。

举世誉之而不加劝,举世非之而不加沮,定乎内外之分,辩乎荣辱之境,斯已矣。 862

你心中最硬核的中国芯是谁?

慕尼黑华南电子展将推出特色活动专区及活动包括:智慧出行科技园、物联网科技园、硬核中国芯科技园、特斯拉model3拆解秀,以及意在扶植华南初创企业的创新公园。通过更深入的交流学习及系统集成...

634

ESP-IDF静态库实战:从组件原理到链接错误排查

在嵌入式开发中,静态库(.a文件)是代码复用和模块化协作的核心载体,尤其在ESP-IDF框架下,每个组件最终都会被编译成静态库再统一链接。理解这一构建机制,是高效排查undefined reference等链接问题的关键。ESP-IDF通过组件目录和CMakeLists组织源码,编译后生成独立的目标文件并打包,链接时按需提取符号。静态库不仅有助于保护知识产劝、加速增量编译,还能通过-ffunction-sections和--gc-sections等选项有效控制固件体积。在实际的ESP32、ESP32-S3、

weixin_27869497的博客 233
上一篇: 浅谈电力电子中的双脉冲测试
下一篇: C硬核:聊聊预编译指令和宏的应用场景(二)
Cerman
博客等级 码龄11年 63粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cerman

你的鼓励是探索和创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值