C语言详细分析宏定义与预处理命令的应用

目录
  • 宏定义与预处理命令
  • 预处理命令 - 宏定义
    • 定义符号常量
    • 定义傻瓜表达式
    • 定义代码段
    • 预定义的宏
  • 函数 VS 宏定义
  • 预处理命令 - 条件式编译
  • 示例

宏定义与预处理命令

  • 预处理阶段:处理宏定义与预处理命令;
  • 编译期:检查代码,分析语法、语义等,最后生成.o或.obj文件;
  • 链接期:链接所有的.o或.obj文件,生成可执行文件。

预处理命令 - 宏定义

定义符号常量

#define PI 3.1415926
#define MAX_N 10000

定义傻瓜表达式

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

定义代码段

\ 为连接符

#define P(a) { \
	printf("%d\n", a); \
}

预定义的宏

常见的预定义的宏

说明
__ DATE__ 日期:Mmm dd yyyy
__ TIME__ 时间:hh:mm:ss
__ LINE__ 行号
__ FILE__ 文件名
__ func__ 函数名/非标准
__ FUNC__ 函数名/非标准
__ PRETTY_FUNCTION__ 更详细的函数信息/非标准

示例:

#include<stdio.h>
int main(){
	//首次编译的时间
	//[Jun 10 2022 09:46:48]
	printf("[%s %s]\n", __DATE__, __TIME__);
	//代码行号:文件名:函数名
	//[6 : E:\2023考研\专业课\C语言\define.cpp : main]
	printf("[%d : %s : %s]\n", __LINE__, __FILE__, __func__);
	return 0;
}

函数 VS 宏定义

作用时期:函数作用在编译期,宏定义作用在预编译期;

使用:函数需要利用额外的栈,因此需要额外的时间开销,相比宏定义更加节约时间但会浪费更多空间;

预处理命令 - 条件式编译

函数 说明
#ifdef DEBUG 是否定义了BEBUG宏
#ifndef DEBUG 是否没定义DEBUG宏
#if MAX_N == 5 宏 MAX_N 是否等于5
elif MAX_N == 4 否则宏MAX_N是否等于4
#else  
#endif  

示例:

#include<stdio.h>
//定义DEBUG宏
#define DEBUG
//判断是否定义了DEBUG宏
#ifdef DEBUG
#define MAX_N 1000
#else
#define MAX_N 100
#endif
int main(){
	int arr[MAX_N + 5] = {0};
	//如果没定义了DEBUG宏 则结果为 420 个字节
	//如果定义了DEBUG宏,则结果为 4020 个字节
	printf("sizeof(arr) = %lu \n", sizeof(arr));
	return 0;
}

示例

没有BUG的MAX宏

#define MAX(a, b)({\
	__typeof(a) _a = a;\
	__typeof(b) _b = b;\
	_a > _b ? _a:_b;\
})

打印LOG的函数,输出所在函数及行号等信息

#include<stdio.h>
//打开log宏
#define DEBUG
//条件式编译
//变参宏
//args加##后表连接 此时args可为空
#ifdef DEBUG
#define log(format, args...){\
	printf("[%s : %s : %d] ", __FILE__, __func__, __LINE__);\
	printf(format, ##args);\
	printf("\n");\
}
#else
#define log(format, args...)
#endif
int main(){
	int a = 123, b = 13;
	//[E:\2023考研\专业课\C语言\log.cpp : main : 12] a = 123, b = 13
	log("a = %d, b = %d", a, b);
	//[E:\2023考研\专业课\C语言\log.cpp : main : 13] hello
	log("hello");
	return 0;
} 

到此这篇关于C语言详细分析宏定义与预处理命令的应用的文章就介绍到这了,更多相关C语言宏定义内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中宏定义的妙用方法

    最近看了intel在linux内核中的驱动,学习到了一个非常有用的小技巧,如下代码: #define IN #define OUT #define UAdress volatile unsigned int * #define Raw_buffer void * void SetHwiPortsDataReg(IN UAdress Register , IN int value) { _SetHwiPortsDataReg(Register,&value); } void _Out_Put_va

  • C语言详细分析宏定义的使用

    目录 一.C语言中函数的“缺陷” 二.再次理解函数 三.C语言中的宏 四.宏与函数的不同 五.编译器组成简介 六.宏使用示例 七.再论宏常量 八.小结 一.C语言中函数的“缺陷” 实参和形参之间仅仅是值传递,因此,函数中无法直接改变实参. 二.再次理解函数 函数是一种代码复用的手段 把实现某个功能的代码片段进行封装(当作一个整体) 给这个代码片段一个合适的名字(通过名字使用代码) 定义参数(定义代码片段需要处理的问题) 三.C语言中的宏 宏是C语言中代码复用的补充方式 宏定义语法:#define

  • C语言#define拼接宏定义实现方式

    使用场合:拼接两个宏,一个是传入的宏.但是传入的宏不会被替换,反而原封不动的接了上去,这就尴尬了.经过各种尝试,居然成了,特此记录分享一下,方便大家学习. char A_param=0; char B_pramm=0; //添加宏定义 #define OBJECT A #define DEFINE_(X) X##_param //一次定义 #define DEFINE(X) DEFINE_(X) //再次定义 #define PARAM DEFINE(OBJECT) void fun() { /

  • C语言之预处理命令的深入讲解

    c提供的预处理功能有: 宏定义 文件包含 条件编译 为了与其她c语句区分,命令经常以符号"#"开头. 宏定义 #define 标识符 字符串 可以避免反复输入字符串,后面不加:宏定义在默认时的有效范围是全部.也可以用#undef终止宏定义区域. 不含参数 宏展开带入程序 含参数 #include<stdio.h> #define PI 3.1415 #define S(r) PI*r*r int main() { int a; float area; scanf("

  • 详解C语言#define预处理宏定义

    目录 #define介绍: #define宏定义无参的一般形式为:#define  标识符 常量 #define宏定义有参的一般形式为:#define  标识符(参数表) 表达式 #运算符: ##运算符: 可变宏...和__VA_ARGS__: 开发项目中常用的宏定义: #define介绍: C语言里可以用#define定义一个标识符来表示一个常量.特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了,也不做类型定义.预编译又叫预处理.预编译就是编译前的处理.这个操作是在

  • C语言宏定义#define的使用

    目录 无参宏定义 定义形式 带参宏定义 定义形式 #和##运算 #运算 用法: ##运算 用法: 变参宏 #ifndef 条件编译 宏定义是高级语言编译器提供的常用语法,其目的是利用某一标识符标识某个文本字符串.在编写程序时,如果程序中反复地使用某个数据或某段程序片段,就可以考虑将这个数据或程序片段定义为宏,然后每个出现该数据或程序片段的地方用宏名替代,选择宏定义来做的好处是程序简洁,可读性好,而且当需要修改这些相同的程序片段时,只要修改宏定义中的字符串即可,不需要修改多处. 宏定义命令:def

  • C语言预处理预编译命令及宏定义详解

    目录 程序翻译环境和执行环境 翻译环境:详解编译+链接 1. 编译 - 预处理/预编译 test.c ---- test.i 2. 编译 - 编译 test.i ---- test.s 3. 编译 - 汇编 test.s ---- test.obj 4. 链接 test.obj ---- test.exe 运行环境 预处理/预编译详解 #define 定义标识符 #和## #的作用 ##的作用 命名约定 命令行定义 条件编译 常见的条件编译指令 文件包含 offsetof(宏类型,成员名字)偏移

  • C语言详细分析宏定义与预处理命令的应用

    目录 宏定义与预处理命令 预处理命令 - 宏定义 定义符号常量 定义傻瓜表达式 定义代码段 预定义的宏 函数 VS 宏定义 预处理命令 - 条件式编译 示例 宏定义与预处理命令 预处理阶段:处理宏定义与预处理命令: 编译期:检查代码,分析语法.语义等,最后生成.o或.obj文件: 链接期:链接所有的.o或.obj文件,生成可执行文件. 预处理命令 - 宏定义 定义符号常量 #define PI 3.1415926 #define MAX_N 10000 定义傻瓜表达式 #define MAX(a

  • C语言详细分析讲解struct与union使用方法

    目录 一.struct 的小秘密 二.结构体与柔性数组 三.C语言中的 union 四.小结 一.struct 的小秘密 C语言中的 struct 可以看作变量的集合 struct 的问题:空结构体占用多大内存?下面编写程序看一下吧: #include <stdio.h> struct TS { }; int main() { struct TS t1; struct TS t2; printf("sizeof(struct TS) = %d\n", sizeof(stru

  • C语言详细分析讲解多文件的程序设计

    目录 一.多文件与编译器链接 二.多文件之间的相互访问 三.关于#include 四.头文件使用的一些原则 五.再论全局变量 六.注意事项 七.实验程序 八.小结 一.多文件与编译器链接 如下图所示,.o 为目标文件,链接器将不同的目标文件装配组合在一起形成一个可执行文件. 二.多文件之间的相互访问 每个文件可以定义功能接口(可被其它文件访问的函数或数据) 源文件:代码实现文件,后缀为.c 头文件:源文件的接口定义文件,后缀为.h 当需要使用其它文件提供的功能时,包含对应的头文件 语法: #in

  • C语言详细分析讲解关键字enum与sizeof及typedef的用法

    目录 一.枚举类型的使用方法 二.sizeof 关键字的用法 三.typedef 的意义 四.小结 一.枚举类型的使用方法 enum 是 C 语言中的一种自定义类型 enum 值是可以根据需要自定义的整型值 第一个定义的 enum 值默认为 0 默认情况下的 enum 值是在前一个定义值的基础上加 1 enum 类型的变量只能取定义时的离散值 enum 中定义的值是C语言中真正意义上的常量 在工程中 enum 多用于定义整型常量 下面看一段 enum 的使用代码吧: #include<stdio

  • C语言详细分析讲解关键字const与volatile的用法

    目录 一.const 只读变量 二.const 全局变量的分歧 三.const 的本质 四.const 修饰函数参数和返回值 五.volatile 解析 六.小结 一.const 只读变量 const 修饰的变量是只读的,本质还是变量 const 修饰的局部变量在栈上分配空间 const 修饰的全局变量在全局数据区分配空间 const 只在编译期有用,在运行期无用 const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边. 二.const 全局变量的分歧 在现代C语言编

  • C语言详细分析讲解关键字goto与void的作用

    目录 一.关于goto 二.void 的意义 三.小结 一.关于goto 高手潜规则:禁用 goto 项目经验:程序质量与 goto 的出现次数成反比 最后的判决:将 goto 打入冷宫 下面看一段 goto 副作用分析的代码: #include <stdio.h> #include <malloc.h> void func(int n) { int* p = NULL; if( n < 0 ) { goto STATUS; } p = (int*)malloc(sizeof

  • C语言详细分析讲解内存管理malloc realloc free calloc函数的使用

    目录 C语言内存管理 一.动态空间申请 二.动态空间的扩容 三.释放内存 C语言内存管理 malloc && realloc && free && calloc c语言中为了进行动态内存管理,<stdlib.h>中提供了几个函数帮助进行内存管理. 我们知道,C语言中是没有C++中的容器或者说是python中list,set这些高级的数据结构的,我们一旦申请了一段内存空间以后这一段空间就归你了,比如我们举个例子,我们申请一个数组 int nums[

  • C语言详细分析贪心策略中最小生成树的Prime算法设计与实现

    目录 浅析最小生成树 Prime算法思想 此算法核心部分 结构体的选择 实现思路 构造实例 构造过程 代码详解 调试结果 总结 浅析最小生成树 设G=(V,E)是无向连通带权图.E中每条边(v,w)的权为c[v][w]. 生成树:如果G的子图G’是一棵包含G的所有顶点的树,则称G’为G的生成树. 耗费:生成树上各边权的总和 最小生成树:在G的所有生成树中,耗费最小的生成树最小生成树在实际中有广泛应用. 例如,在设计通信网络时,用图的顶点表示城市,用边(v,w)的权c[v][w]表示建立城市v和城

随机推荐