C语言define关键字全解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: C语言define关键字全解析

🧑🏻作者简介:一个走在前行路上的人

✨联系方式:2201891280(QQ)

⏳全文大约阅读时间: 60min


☘前言☘

偷个图,如果用上面的方式写代码,中文编码指日可待有没有?哈哈哈哈

在工程代码中,头文件的最开始就能看到一大片#define,今天我们就看一下define这个关键词究竟是怎么用的。这些知识主要来源于博主最近的实习经历和自己写代码的习惯提炼出来哦。


🧂1.防止重复包含

不知道小伙伴们有没有发现我们就算再我们的c文件里面写了两次#include <stdio.h>也没有提示我们重复包含,但是自己写一个头文件的时候就会提示这个问题。

其实我们看看标准库文件都可以看到一些有趣的应用


#ifnodef __TEST__
#define __TEST__
...
代码段  头文件 blabla
...
#endif


这个的作用就是判断是否定义了一个宏,未定义就进行定义并进行相关变量结构体之类的定义,定义的话就会跳过这部分,可以防止重复定义。

同时这个思维也可以用于debug和正式版的切换,这个等下再说。

🎐2.定义常量

其实这个是我们平常最常见的定义方式了,大家应该都会用吧???是吧是吧?但是呢,有坑。。。。


#define PI 3 + 1
printf("%d",10*PI);


我们得到的结果就是31,因为define就是简单的替换,那么后果就是替换成了10*3+1,所以写宏定义的时候建议统统加上括号,防止出错。

所以上面的就是


#define PI (3+1);
printf("%d",10*PI);


就正常啦。


🕷️3.定义函数

宏定义可以作为一些函数来使用,我举几个例子


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


这个就是一个求最大值的函数,可以看到全加了括号,就是为了防止上面定义常量出现的问题。


#define SWAP(a,b) do{\
  int t = a;\
  a = b;
  b = t;
}while(0);


就可以实现a、b的交换,可以学到一个小知识就是define可以换行只要加上\,同样的思路也可以用在printf中哟。


const double eps = 1e-8;
const double pi = acos(-1.0);
#define Equ(a, b) ((fabs((a) - (b))) < (eps))
#define More(a, b) (((a) - (b)) > (eps))
#define Less(a, b) (((a) - (b)) < (eps))
#define MoreEqu(a, b) (((a) - (b)) > (-eps))
#define LessEqu(a, b) (((a) - (b)) > (eps))


结合比较函数,我们可以写一些浮点数的比较啦扒拉扒拉,感兴趣可以看看我另外一篇文章。1.3 浮点数的比较


🕷️4.#、#@和##

#define TOSTRING(a) #a
#define CONNECT(a,b) a##b
#define TOCHAR(a) #@a //Microsoft Specific


其实看完上面的代码就很简单了#代表的就是将a变成一个字符串,不过需要注意的是这个返回的是一个指针,也可以说字符串数组,whaterver。

然后##有点类似于strcat会将两个连接到一起返回。

#@用于返回一个字符,有人看到我写的Microsoft Specific了么,这玩意微软专属。。。。。所以在linux下的话我看到有两种写法可以实现类似的功能。

#define TOCHAR(a) #a[0]
#define TOCHAR(a) *#a


其实看一眼都是懂得,就是取出第一个元素来变化,有个小点不知道大家有没有发现其实第一行的结合顺序是先#a然后再[0]的,这样才能取出第一个元素。而第二个就是直接解引用了。


🍔5.一些参数

上班第一天的代码给我看傻了


#define DEBUG
#ifdef DEBUG
#define APP_PRINT(...) printf(__VA_ARGS__)
#else
#define APP_PRINT(...)
#endif


这种写法就是为了控制debug版本和正式版本的,其中__VA_ARGS__就是...匹配到的内容,这样就可以直接控制是否输出调试信息,简直牛犇!!!但是注意这个只支持再后面书写如果书写a...b是错误的,...之后不能再加任何信息了,听别人说的,我试了,是真的0.0,只能接括号


🎶6.一些预定义的宏

d6ed76d050a850af16d26dd831ba8d5.png

🍢写在最后

今天就写到这里了,如果大家觉得对你有帮助的话还希望大家动动手指给个三连0.0

你的支持是我前进最大的动力。


相关文章
|
2月前
|
存储 缓存 Java
Java 并发编程——volatile 关键字解析
本文介绍了Java线程中的`volatile`关键字及其与`synchronized`锁的区别。`volatile`保证了变量的可见性和一定的有序性,但不能保证原子性。它通过内存屏障实现,避免指令重排序,确保线程间数据一致。相比`synchronized`,`volatile`性能更优,适用于简单状态标记和某些特定场景,如单例模式中的双重检查锁定。文中还解释了Java内存模型的基本概念,包括主内存、工作内存及并发编程中的原子性、可见性和有序性。
Java 并发编程——volatile 关键字解析
|
2月前
|
存储 网络协议 编译器
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
194 14
|
2月前
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
60 1
|
2月前
|
存储 编译器 C语言
【C语言】数据类型全解析:编程效率提升的秘诀
在C语言中,合理选择和使用数据类型是编程的关键。通过深入理解基本数据类型和派生数据类型,掌握类型限定符和扩展技巧,可以编写出高效、稳定、可维护的代码。无论是在普通应用还是嵌入式系统中,数据类型的合理使用都能显著提升程序的性能和可靠性。
77 8
|
2月前
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
768 6
|
2月前
|
Java 程序员
面试官的加分题:super关键字全解析,轻松应对!
小米,29岁程序员,通过一个关于Animal和Dog类的故事,详细解析了Java中super关键字的多种用法,包括调用父类构造方法、访问父类成员变量及调用父类方法,帮助读者更好地理解和应用super,应对面试挑战。
50 3
|
2月前
|
存储 网络协议 算法
【C语言】进制转换无难事:二进制、十进制、八进制与十六进制的全解析与实例
进制转换是计算机编程中常见的操作。在C语言中,了解如何在不同进制之间转换数据对于处理和显示数据非常重要。本文将详细介绍如何在二进制、十进制、八进制和十六进制之间进行转换。
93 5
|
2月前
|
C语言 开发者
【C语言】断言函数 -《深入解析C语言调试利器 !》
断言(assert)是一种调试工具,用于在程序运行时检查某些条件是否成立。如果条件不成立,断言会触发错误,并通常会终止程序的执行。断言有助于在开发和测试阶段捕捉逻辑错误。
60 5
|
2月前
|
安全 搜索推荐 Unix
【C语言】《回调函数》详细解析
回调函数是指一个通过函数指针调用的函数。它允许将一个函数作为参数传递给另一个函数,并在特定事件发生时执行。这种技术使得编程更加灵活,可以动态决定在何时调用哪个函数。
86 1
|
程序员 PHP C语言

推荐镜像

更多