#ifdef #endif #ifndef 定义+代码详解

本文详细解读了C/C++中的预处理指令ifdef、ifndef及其在条件编译中的作用。通过实例展示了如何根据标识符定义与否控制源代码编译,并介绍了ifndef用于相反条件的情况。还介绍了在头文件中使用这些指令防止双重定义的技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 这些代码是什么?属于C/C++中什么类型的词?

#ifdef  #endif  #ifndef 属于C/C++预处理指令,常见的预处理指令还包括#include #define #undef #elif #error等。

预处理指令定义预处理指令是以 #号开头 的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是 指令关键字 ,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在 编译器进行编译之前 对源代码做某些转换。

2. 这些代码出现的意义是什么?

一般情况下,源程序中所有的行都参加编译。C/C++中有个概念叫做条件编译 ”。“条件编译”要求做到对 指定部分 内容编译。当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。而这些预处理指令,可以帮助我们达到这个效果。

3.代码的具体用法及示例(分为实现文件 + 头文件)

实现文件中:

1  ---  标识符被定义(出现#define ***):

#include<iostream>
using namespace std;
#define NYJ

int main()
{
#ifdef NYJ
	cout << "ifdef NYJ" << endl;
#else
	cout << "else" << endl;
#endif
}

运行结果:

 此时因为标识符“NYJ”被定义了,因此编译器会对#ifdef 后面的内容进行编译,与此同时跳过对#else后面内容的编译。

2  ---  标识符没有被定义(不存在#define ***)

运行结果:

 此时标识符“NYJ”未被定义,因此编译器不会对#ifdef后面的内容进行编译,与此同时对#else #endif 后面内容进行编译。

注释:在以上代码中,#else并非必须出现。

ifndef的用法

此外,还有 #ifndef 的用法,顾名思义,ifdef = if define ,而 ifndef = if not define ,与ifdef意思恰好相反,以下是关于它的代码示例:

#include<iostream>
using namespace std;

int main()
{
#ifndef NYJ
	cout << "ifndef NYJ" << endl;
#else
	cout << "else" << endl;
#endif
}

 标识符没有被定义(不存在#define ***)

标识符被定义(出现#define ***)

头文件中:

在头文件中使用 #ifdef 和#ifndef,可以防止双重定义的错误。

例如在头文件 “NYJ.h”中,定义了如下类

class D
{
	int a;
	int b;
};

 双重定义:在 “K.h” 中,由于包含了 NYJ.h ,因此包含了 Class D ,同理,K.h中包含了a.h,而a.h中又包含了NYJ.h,因此Class D被双重定义了,而类是不允许被双重定义的,因此,为防止这种现象发生,我们可以采取如下措施:


#ifndef NYJ_H
//if !define NYJ_H  也可以这样写
#define NYJ_H
class D
{
   int a;
   int b;
};
#endif

这样一来,第一次调用这个头文件的时候,没有定义NYJ_H,就会继续对下面的语段进行声明。但是当第二次调用头文件时,已经定义了NYJ_H,所以就不会进行下面的代码声明了。这就是条件编译防止头文件包含的原理。

这是一段用于确保 `_UNICODE` 和 `UNICODE` 两个宏同时被定义代码,常见于 Windows 平台上涉及 Unicode 字符集处理的情境下。下面我们逐步解析其作用及原理。 --- ### **背景知识** 在 Windows 编程中: - `UNICODE` 宏通常由开发者手动定义,或者通过 IDE 的项目配置开启(例如 Visual Studio 中启用“Unicode字符集”选项时会自动定义此宏)。 - `_UNICODE` 则是由 C 运行时库 (CRT) 引入的一个标志,表示程序应使用宽字符串版本的标准库函数(如 `wcscpy` 替代 `strcpy` 等)。 如果希望应用程序能够正确支持 Unicode,并统一使用宽字符串 API,则需要保证这两个宏始终成对存在。 --- ### **逐句分析** #### 第一部分: ```c #ifdef _UNICODE #ifndef UNICODE #define UNICODE #endif #endif ``` 这一部分的意思是: 如果 `_UNICODE` 已经被定义了(通常是由于 CRT 配置导致),但是 `UNICODE` 尚未定义的话,就强制定义 `UNICODE`。这样做的目的是为了同步两者之间的状态,避免因为只有一个宏被定义而导致潜在的问题。 --- #### 第二部分: ```c #ifdef UNICODE #ifndef _UNICODE #define _UNICODE #endif #endif ``` 这一部分的作用是对称的: 如果 `UNICODE` 已经被定义,而 `_UNICODE` 没有定义的情况下,就会进一步定义 `_UNICODE`。同样是为了保持一致性,使得无论从哪一侧进入,最终都能让两者的值一致。 --- ### **总结** 这段代码的核心思想在于**确保 `_UNICODE` 和 `UNICODE` 始终一起生效或失效**。这种做法非常有用,尤其是在跨团队协作、多人维护源码时,可以减少因忘记定义其中一个宏带来的问题。 此外需要注意的是,在现代开发实践中推荐直接显式地设定编码模式(如 UTF-8 或纯 ASCII),并尽量少依赖类似的历史遗留宏组合。不过如果你仍然工作在一个较老的基础框架上,理解上述内容将是不可或缺的知识点。
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值