【C语言】条件编译的用法(预处理)

目录

什么是预处理?

一、情况1

二、情况2

三、情况3

四、【#if—#elif】

五、文件中的 #ifndef

六、#ifndef精华汇总​​​​​​​


什么是预处理?

预处理就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。
关于预处理命令中的文件包含(#include)宏定义(#define)。这里主要是对条件编译(#ifdef,#else,#endif,#if等)进行说明。以下分3种情况:

一、情况1

#ifdef _XXXX
...程序段1...
#else
...程序段2...
#endif

这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。 

与之对比:

#ifndef _XXXX
...程序段1...
#else
...程序段2...
#endif

这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。 

#ifndef 
...程序段1...
#else
...程序段2...
#endif

例如:

#define NUM
.............
.............
#ifdef NUM
printf("之前NUM有过定义啦!:) \n");
#else
printf("之前NUM没有过定义!:( \n");
#endif

如果程序开头有#define NUM这行,即NUM有定义,碰到下面#ifdef NUM的时候,当然执行第一个printf。否则第二个printf将被执行。用这种,可以很方便的开启/关闭整个程序的某项特定功能。

根据上述情况,我们这次采用c语言的条件编译指令。它的格式是这样的:

简单解释一下就是如果已经用#define定义了tcp_c,则执行TCP_Client这个程序,否则执行TCP_Server这个程序。

二、情况2

#ifndef _XXXX
...程序段1...
#else
...程序段2...
#endif

这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。 

三、情况3

#if 常量
...程序段1...
#else
...程序段2...
#endif

这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。
这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。

四、【#if—#elif】

 #if更加灵活一些,后面可以跟常量表达式,如果表达式为非零值,则表达式为真,否则为假。故可以使用关系运算符和逻辑运算符。

 如果我想在UDP、TCP_Server和TCP_Client三个函数中进行切换,我们可以用上面的语句:

#if #elif #endif

如果工程较大,分散度高,可以使用这种方法,效果是一样的。

#if #endif

五、文件中的 #ifndef

头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。

将头文件的内容都放在#ifndef和#endif中。不管头文件会不会被多个文件引用,都要加上这个。

#ifndef <标识>
#define<标识>

......
......

#endif

<标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h

#ifndef _STDIO_H_//先测试x是否被宏定义过(一般来说指定是没有定义过)
#define _STDIO_H_ //如果x没有被宏定义过,定义x,并编译下述程序

......

#endif //终止if

 在#ifndef中定义变量出现的问题(一般不定义在#ifndef中)。

#ifndef AAA
#define AAA
...
int i;
...
#endif

.h中只声明 extern int i;在.cpp中定义 

#ifndef __X_H__
#define __X_H__
extern int i;
#endif //__X_H__

变量一般不要定义在.h文件中!!!!!

#ifndef GRAPHICS_H // 防止graphics.h被重复引用
#define GRAPHICS_H
#include // 引用标准库的头文件
…
#include “myheader.h” // 引用非标准库的头文件
…
void Function1(…); // 全局函数声明
…
class Box // 类结构声明
{
…
};
#endif

六、#ifndef精华汇总

条件指示符最主要的目的是防止头文件的重复包含和编译。

语句1 #ifndef 标识1 //判断标识1是否定义,如果定义则返回假,如果没有定义则返回真。

语句2 #define 标识1 //如果标识1没有被定义,则重定义标识1。即执行语句2。

语句3 #endif 如果标识1已经被定义,则直接跳过语句2、语句3。直接执行语句4、语句5。

语句4 ......

语句5 ......

备注:#ifndef 和 #endif 要一起使用,如果丢失#endif,可能会报错。

需要注意的是,#ifndef起到的效果是防止一个源文件两次包含同一个头文件,而不是防止两个源文件包含同一个头文件。网上很多资料对这一细节的描述都是错误的。事实上,防止同一头文件被两个不同的源文件包含这种要求本身就是不合理的,头文件存在的价值就是被不同的源文件包含。

例如要编写头文件test.h,在头文件开头写上两行:

#ifndef _TEST_H

#define _TEST_H //一般是文件名的大写

头文件结尾写上一行:

#endif

这样一个工程文件里同时包含两个test.h时,就不会出现重定义的错误了。

当第一次包含test.h时,由于没有定义_TEST_H,条件为真,这样就会包含(执行)#ifndef _TEST_H和#endif之间的代码,当第二次包含test.h时前面一次已经定义了_TEST_H,条件为假,#ifndef _TEST_H和#endif之间的代码也就不会再次被包含,这样就避免了重定义了。

而把头文件的内容都放在#ifndef和#endif中,则无论头文件会不会被多个文件引用,都需要加上这个。一般格式是这样的:

#ifndef <标识>

#define <标识>

......

......

#endif

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C语言中,预处理是指在编译阶段之前对源代码进行处理的过程,它由编译器的预处理器执行。预处理器会根据以符号#开头的预处理命令,对源代码进行一系列的处理和替换操作。预处理命令可以用来包含头文件、定义宏、条件编译等。 其中,预处理命令#include用于包含其他文件。被包含的文件可以是普通的C语言源程序文件(.c文件),也可以是C语言程序的头文件(.h文件)。在C语言系统中,大量的定义与声明是以头文件形式提供的。通过#include命令,我们可以将头文件中的内容插入到当前源文件中,以便在程序中使用头文件中定义的函数、变量或宏等。 总结起来,预处理C语言中的用法主要包括使用#include命令来包含头文件,以及其他预处理命令用于定义宏、进行条件编译等操作。这些预处理命令能够扩展C语言程序设计的环境,提供了更灵活和高效的代码编写方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C语言中的预处理详解](https://blog.csdn.net/weixin_32445333/article/details/117124370)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

米杰的声音

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值