c++条件编译详解

c++条件编译详解

本篇文章专注于解答在《c++预处理器》一文中提出的问题,并进一步提升对c++条件编译的认识。

通常,源文件中所有内容都要参加编译,但是在某些时候,可能希望源文件中某些部分在满足某些条件的情况下才进行编译,这就是所谓的条件编译

有趣的是,对于c++的初学者来说,没有条件编译照样可以写出可以良好运行的程序,所以条件编译的知识常常会被忽视。

但事实上,条件编译非常有用。要注意,对于一些小型的程序,条件编译的作用可能常常被掩盖,但是当程序的规模变大后条件编译的作用和优势就会显现出来了。因此把握它还是非常重要的。

条件编译的形式

条件编译有以下三种形式:

形式一


#ifdef  标识符
   程序片段1
#else  
 程序片段2
#endif

上述语句的意思就是如果标识符已被#define命令定义过,则对程序片段1进行编译;否则对程序片段2进行编译。其中,程序片段2可以为一个空的程序段,那么#else就没有什么实际的意义了,这时可以将其省略。

请看下面看这段示例代码。

#include <iostream>
#define DEBUG
using namespace std;
void main()
{
#ifdef DEBUG 
 cout << "Begin..." << endl;
#else
 cout << "Cannot Begin!" << endl;
#endif
 int array[10];
 for(int i = 0;i < 10;i++)
 {
  array[i] = i;
#ifdef DEBUG 
 cerr << "i = " << i << endl;
 cerr << "array[i] = " << array[i] << endl;
#endif
 }
}

形式二

#ifndef 标识符
 程序片段1
#else
 程序片段2
#endif

形式2和形式1的区别在于#ifdef关键字换成了#ifndef关键字,其功能是如果标识符未被

define命令定义过,则对程序片段1进行编译;否则对程序片段2进行编译,这与形式1的

功能正好相反。

形式三

#if 标识符
 程序片段1
#else
 程序片段2
#endif

该形式完成的功能是如果表达式的值为真,则对程序片段1进行编译;否则对程序片段2
进行编译。因此可以使程序在不同条件下完成不同的功能。

条件编译的使用场景

1、避免头文件重复包含和变量重复定义

在c或c++中,头文件重复包含问题是程序员必须避免的问题,也是很多新手容易犯错的问题。

请读者先先思考这样一段代码:(方便起见将三个文件的代码写在一起)

//a.h
#include<stdio.h>
int A=1;
 
 
//b.h
#include "a.h"
void f(){printf("%d",A);}
 
//main.c
#include<stdio.h>
#include"a.h"
#include"b.h"
void main(){f();}

编译运行此程序会报错,提示你int A 被重复定义。

为什么会出现这样的问题呢,我们要从头文件的编译预处理说起。

我们知道在编译c或c++程序时候,编译器首先要对程序进行预处理,预处理其中一项工作便是将你源程序中#include的头文件完整的展开

于是乎,当出现头文件重复包含时,就会带来两种不利影响:

1、编译器编译步骤多次编译该头文件,工程代码量小还好,工程量一大会使整个项目编译速度变的缓慢,后期的维护修改变得困难。

2、头文件里对变量的多次定义会使程序在编译链接的时候崩溃。

解决:

头文件重复包含和变量重复定义可以借由条件编译解决,代码如下:

//a.h

#ifndef _A_H
#define _A_H
 
int A = 1;
 
#endif;

通过条件编译,实现了a.h只编译一次。

此外,微软的vs和vscode还提供了#pragma one预编译指令,其作用与条件编译相同。

//a.h
 
#pragma once
#include<stdio.h>
int A = 1;

2、交叉功能的项目文件

一些客户需要你这个产品里的功能A而另外一些客户不需要A,那么你就可以使用条件编译把实现A的所有代码包起来,这样你就可以#define和#undef来enable或者disable你的功能A了

3、便于文件调试

在形式一的样例代码中展现过这样的思路,即将调试过程中的附加代码用#ifdef DEBUG包起来,在预编译指令中通过加入与删除#define DEBUG来实现调试过程与最终代码之间的切换。

posted @ 2021-01-23 22:32  未徙  阅读(1872)  评论(0)    收藏  举报