#undef的语法

定义:#undef 标识符,用来将前面定义的宏标识符取消定义。

整理了如下几种#undef的常见用法。

1. 防止宏定义冲突
在一个程序块中用完宏定义后,为防止后面标识符冲突需要取消其宏定义。

例如:

#include <stdio.h>

int main()
{
#define MAX 200
printf("MAX = %d\n", MAX);
#undef MAX int MAX = ;
printf("MAX = %d\n", MAX); return ;
}

在一个程序段中使用完宏定义后立即将其取消,防止在后面程序段中用到同样的名字而产生冲突。

2.增加代码可读性
在同一个头文件中定义结构类型相似的对象,根据宏定义不同获取不同的对象,主要用于增强代码的可读性。

例如:在头文件student.h中定义两个学生对象(小明和小红),两个对象互不干涉。

#ifdef MING
#define MING_AGE 20
#define MING_HEIGHT 175
#endif

#ifdef HONG
#define HONG_AGE 19
#define HONG_HEIGHT 165
#endif

在源文件中使用这两个对象:

#include <stdio.h>

#define MING
#include "student.h"
#undef MING
#define HONG
#include "student.h"
#undef HONG int main()
{
printf("Xiao Ming's age is %d.\n", MING_AGE);
printf("Xiao Hong's age is %d.\n", HONG_AGE); return ;
}

在一个头文件里定义的两个对象与分别在两个头文件里定义效果相同,但如果将相似的对象只用一个头文件申明,可以增强源代码的可读性。

3. 自定义接口
将某个库函数包装成自定义接口,而只允许用户调用自定义接口,禁止直接调用库函数。

例如,自定义安全的内存分配器接口:

/*
** 定义一个不易发生错误的内存分配器
*/
#include <stdlib.h> #define malloc //防止直接调用malloc!
#define MALLOC(num, type) (type *)alloc((num) * sizeof(type))
extern void *alloc(size_t size);

其中“#define malloc”是为了防止用户直接调用库函数malloc,只要包含了这个头文件alloc.h,就不能直接调用库函数malloc,而只能调用自定义函数MALLOC,如果用户要调用库函数malloc编译器会发生错误。

自定义安全的内存分配器的实现:

/*
** 不易发生错误的内存分配器的实现
*/
#include <stdio.h>
#include "alloc.h"
#undef malloc void *alloc(size_t size)
{
void *new_mem;
new_mem = malloc(size);
if(new_mem == NULL)
{
printf("Out of memory!\n");
exit();
}
return new_mem;
}

因为在实现中需要用到库函数malloc,所以需要用这一句“#undef malloc”取消alloc.h中对malloc的宏定义。

这种技巧还是比较有意思的,用于对已经存在的库函数进行封装。而且如果包含了自定义接口文件,就不能直接调用库函数,而只能调用自定义封装的函数。

4. 用于调试头文件中
用于调试头文件中,偶然看到这样一个代码用到了#undef,写于此作为记录:

#ifdef _DEBUG_
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif

undef用法的更多相关文章

  1. winform中messageBox七个参数的使用(转载)

    private void button1_Click(object sender, EventArgs e) { MessageBox.Show(" 1 个参数 ”); } private ...

  2. C#中的预编译指令介绍

    原文:C#中的预编译指令介绍 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量 ...

  3. Perl语言入门--2--变量与字符串

    一.$ 简单变量:$          以$开头+字母或下划线 区分大小写,变量长度不限,没有关键字,但不能和默认变量重复 1.整数的表示: 12 12e2 #1200 -12 #-12 1_200_ ...

  4. C#中的预编译指令介绍[转]

    原文链接 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量,但是它没有具体的值 ...

  5. #define #include #undef的其中一个用法(目的)

    一.背景 最近在跟一段系统级的代码,和原来单纯的下位机代码相比,真的是刘姥姥进大观园--看花了眼.相较于 之前所常见的各种下位机代码,系统级代码常常会出现深层次结构体嵌套,结构体内的各种回调函数导致对 ...

  6. #undef常用法

    Copy from C语言中#undef的语法是: #undef 标识符 用来将前面定义的宏标识符取消定义. 整理了如下几种常见用法,如果以后发现其他的再添加进来. 1.在一个程序块中用完宏定义后,为 ...

  7. 预处理命令#define #undef #if #endif 的基本用法

    C#的预处理命令其实还是蛮有用的,但是真正使用过得人不多,这个介绍一下平时用的比较多的预处理命令中的几个:#define,#undef ,#if,#endif.除此之外还有一些预处理命令#warnin ...

  8. #undef及其用法

    简    介 在后面取消以前定义的宏定义 在此程序中,我们将取消在先前程序中对预处理器的定义. #include <stdio.h> int main( void ) { #define ...

  9. #undef 的用法

    在Visual Studio2008中编写如下代码: #include <iostream> using namespace std; int main() { #define MODI ...

随机推荐

  1. Python库-Matplotlib

    Matplotlib官网https://matplotlib.org,Matplotlib是一个Python的2D绘图库. 可视化是整个数据分析的关键辅助工具,可以清晰的理解数据. 折线图(用于显示数 ...

  2. 聊一聊深拷贝和浅拷贝(JS)

    在 JS 中数据类型分为值类型和引用类型,对于值类型,变量中存放的是具体的值,而对于引用类型,变量中存放的是地址. 对于值类型: const a = 3; let b = a; b = 4; cons ...

  3. 列表推导式和seed()的理解

    Table of Contents generated with DocToc 列表推导式和seed()的理解 对seed()的理解 列表推导式 第一种用法 第二种用法 列表推导式和seed()的理解 ...

  4. stand up meeting 12/01/2015

    part 组员 今日工作 工作耗时/h 明日计划 工作耗时/h UI 冯晓云   赶工sprint3,各部分要合在一起时出现各种问题,各种修改测试:UI本身的功能继续实现完善    6 UWP对控件的 ...

  5. 1个工具,助你提升K8S故障排查效率!

    Kubernetes的故障排查一直困扰众多运维团队或DevOps,除了Kubernetes本身的复杂性之外,还有Kubernetes的工作负载是动态的原因.本文将介绍1个工具可以帮助你可视化K8S的网 ...

  6. B - Fadi and LCM CodeForces - 1285C 质因子

    题目大意很简单,给你一个整数X,让你求a和b,使得max(a,b)尽可能的小,然后打印a,b 题解:想到了质因子分解,也考虑到了暴力,但是觉得暴力的话会TLE,所以打算用贪心做,然后就一直Wa.... ...

  7. Laravel 分页 数据丢失问题解决

    问题: to do list 中有32条数据,每页10条,共3页. 做完了一个事项之后,准备打卡,发现找不到这个事项. 数据库查询正常,有这一条数据. 原因: 发现是分页出了问题,第1页的数据和第2页 ...

  8. Scapy的基本使用

    关于Scapy Scapy是一个可以让用户发送.侦听和解析并伪装网络报文的Python程序.这些功能可以用于制作侦测.扫描和攻击网络的工具. 换言之,Scapy 是一个强大的操纵报文的交互程序.它可以 ...

  9. for嵌套setTimeout的心得

    export default { data() { return { dialogList: [] } }, created() { this.setList() }, methods: { setL ...

  10. 2019-2020-1 20199308《Linux内核原理与分析》第三周作业

    <Linux内核分析> 第二章 操作系统是如何工作的 2.1 函数调用堆栈 3个关键性的方法机制(3个法宝) 存储程序计算机 函数调用堆栈机制 中断 堆栈相关的寄存器 ESP:堆栈指针(s ...