C语言中——详解条件编译的妙用#ifdef_thorough

 2024-01-26 00:04:36  阅读 0

本文主要介绍C语言中条件编译相关的预编译指令,包括#、#undef、#ifdef、#、#if、#elif、#else、#endif。

#定义一个预处理宏

#undef 取消定义宏

#if 编译预处理中的条件命令,相当于C语法中的if语句

#ifdef 确定是否定义了宏。 如果定义了,则执行后面的语句。

# 与#ifdef相反,判断宏是否未定义

#elif 如果#if、#ifdef、#或前面的#elif条件不满足,则执行#elif后面的语句,相当于C语法中的else-if

#else对应#if、#ifdef、#。 如果不满足这些条件,则会执行#else后面的语句,相当于C语法中的else。

#endif #if、#ifdef、#End 这些条件命令的标志。

与#if、#elif配合使用,判断宏是否定义

2. 条件编译

条件编译是一种基于实际定义的宏(某些类型的条件)静态编译代码的方法。 编译条件可以根据表达式的值或是否定义了特定的宏来确定。

最常见的条件编译是为了防止头文件中重复包含宏,类似于下面的代码:

1 #ifndef ABCD_H
2 #define ABCD_H
3 
4 // ... some declaration codes
5 
6 #endif // #ifndef ABCD_H

实现文件中通常有类似如下的定义:

 1 #ifdef _DEBUG
 2 
 3 // ... do some operations
 4 
 5 #endif
 6 
 7 #ifdef _WIN32
 8 
 9 // ... use  Win32 API
10 
11 #endif

这些是条件编译的常见场景。

3.条件编译中使用的预编译指令

#定义一个预处理宏

#undef 取消定义宏

#if 编译预处理中的条件命令,相当于C语法中的if语句

#ifdef 确定是否定义了宏。 如果定义了,则执行后面的语句。

# 与#ifdef相反,判断宏是否未定义

#elif 如果#if、#ifdef、#或前面的#elif条件不满足,则执行#elif后面的语句,相当于C语法中的else-if

#else对应#if、#ifdef、#。 如果不满足这些条件,则会执行#else后面的语句,相当于C语法中的else。

#endif #if、#ifdef、#End 这些条件命令的标志。

与#if、#elif配合使用,判断宏是否定义

4. 预编译指令应用示例 1. #、#undef

#定义了一个宏:

# [(args)] [[(opt)]]

后续出现的内容将被定义的 tag() 替换。 宏可以带参数,以下标签是可选的。

宏定义通常根据是否带参数分为对象宏和函数宏。

对象宏:不带参数的宏称为“对象宏”。 对象宏主要用于定义常量和通用标识符。 例如:

// 常量定义
#define MAX_LENGTH 100
// 通用标识,日志输出宏
#define SLog printf
// 预编译宏
#define _DEBUG

功能宏:带参数的宏。 使用宏可以提高代码的运行效率:调用子程序需要压栈和出栈。 如果这个过程过于频繁,就会消耗大量的CPU计算资源。 因此,如果一些体积较小但运行频繁的代码采用带参数的宏来实现,将会提高代码的运行效率。 不过,对于大多数C++程序,不建议使用函数宏,而且调试起来很困难。 您可以考虑使用 C++ 代替。 例如:

// 最小值函数
#define MIN(a,b) ((a)>(b)? (a):(b))
// 安全释放内存函数
#define SAFE_DELETE(p) {if(NULL!=p){delete p; p = NULL;}}

#undef可以取消宏定义,对应#。

2.

用于测试宏是否被定义。 (name):如果定义了宏,则返回 1,否则返回 0。

它与#if、#elif 和#else 结合使用来确定宏是否已定义。 乍一看,这似乎是多余的,因为已经有#ifdef和#了。 可用于在一个判断语句中声明多个判断条件; #ifdef和#只支持判断宏是否定义。

#if defined(VAX) && defined(UNIX) && !defined(DEBUG) 

与#if、#elif 和#else 不同,#ifdef、# 和测试宏可以是对象宏或函数宏。

3.#ifdef、#、#else、#endif

条件编译中比较常用的预编译指令。 模式如下:

#ifdef ABC
// ... codes while definded ABC
#elif (CODE_VERSION > 2)
// ... codes while CODE_VERSION > 2
#else
// ... remained cases
#endif // #ifdef ABC 

#ifdef用于判断宏是否定义,与#函数正好相反。 它们仅支持确定是否已定义单个宏。 在上面的例子中,两者可以互换。 如果不需要多条件预编译,上例中的#elif和#else就可以不用写。

4.#if、#elif、#else、#endif

#if可以支持同时判断多个宏是否存在,与常量表达式结合使用。 常用的格式如下:

#if 常量表达式1
// ... some codes
#elif 常量表达式2
// ... other codes
#elif 常量表达式3
// ...
...
#else
// ... statement
#endif

常量表达式可以是包含宏、算术运算、逻辑运算等的合法C常量表达式。如果常量表达式是未定义的宏,则其值被视为0。

#if MACRO_NON_DEFINED // 等价于
#if 0

在判断宏是否定义时,应避免使用#if,因为宏的值可能被定义为0。而应使用#ifdef或#。

注意:#if和#elif之后的宏只能是对象宏。 如果宏没有定义,或者宏是函数宏,编译器可能会发出警告,指出相应的宏没有定义。

5. 总结

本文主要介绍C语言中的预编译指令。 写这篇文章的目的是为了理清相关概念调用,以便后续预编译和使用时能够找到最合适的指令和格式。 比如同时满足多个宏定义的预编译、多分支预编译以及#elif和#else指令的配合等。

1.如果是条件编译,选择编译

(1)

#如果()

//********

#万一

(2)

#如果()

//*****

#别的

//*****

#万一

(3)

#如果()

//*****

#elif()

//*****

#elif()

//*****

#万一

2、注意这里不能加“()”,否则括号会被认为是宏定义的字符串。

#DBG

三,

#AC(0,1...)

4、注意这里不能加“()”,否则括号会被视为宏定义字符串。

#DBG

#DBG

5、注意这里不能加“()”,否则括号会被认为是宏定义的字符串。

(1)

#ifdef DBG

#UNDBG

#

#万一

(2)

#DBG

#UNDBG

#UNDBG

#万一

6、满足条件“&&和||”的复合条件必须加上标准形式“()”如:# if ( (DBG)) || ((DBG1))

(1)

# 如果 DBG || DBG1 || 数据库G2

//*****

#万一

(2)

#如果 ! 数据库组|| ! 数据库G2

//*****

#万一

1. 条件编译

请看下面的例子:

 

#

#BB

#ifdef AA

# 你好“你好世界”

#

# 你好“你好CC”

#主要的()

("%s\n",你好);

1;

如果你认为这张照片会是你好,CC。 那你就犯了和我一样的错误。 如果使用 gcc -E hello.c -o hello.i 来编译,(这是一个预编译命令,下面会讲到)就会出现错误:error: #if with no。 原因是虽然定义了BB,但是定义了一个空值,如果放在#elif后面就不起作用。 因为#elif不仅检查后面的宏是否定义,还检查它的值。 但 #ifdef 只是检查后面的宏是否已定义,而不管其值如何。 读者可以把#

尝试将 BB 更改为 # AA,结果将是 hello world。

如果读者有兴趣,也可以尝试一下,将#BB改为#BB 0。此时用gcc -E hello.c -o hello.i预编译可以通过,但编译过程会不起作用,因为 #elif 0 如果为 false,则未定义 HELLO。

这些宏用于条件编译。 一般情况下,源程序中的所有行都会包含在编译中。 但有时你只想在满足某些条件时才编译部分内容,即指定编译部分内容的条件。 这就是“条件编译”。 有时,您希望在满足某个条件时编译一组语句,在不满足条件时编译另一组语句。

条件编译命令最常见的形式是:

#ifdef 标识符

节目片段1

#别的

节目片段2

#万一

其作用是:当标识符已经定义(一般用#命令定义)时,编译程序段1,否则编译程序段2。

#else部分不需要包含,即:

#ifdef

节目片段1

#denif

这里的“程序段”可以是语句组,也可以是命令行。 这种条件编译可以提高C源程序的通用性。 如果一个C源程序运行在不同的计算机系统上,而不同的计算机有一定的差异。 例如,我们有一种数据类型,在一个平台上应该用 long 类型表示,但在其他平台上应该用 float 类型表示。 这往往需要对源程序进行必要的修改,从而降低了程序的通用性。 满足以下条件即可编译:

#ifdef

# 长的

#别的

# 漂浮

#万一

如果在 上编译程序,可以在程序开头添加

#

这将编译以下命令行:

# 长的

如果这组条件编译命令之前出现如下命令行:

#0

那么预编译程序中的所有内容都会被float替换。 这样,源程序无需任何修改就可以在不同类型的计算机系统上使用。 当然,上面的介绍只是一个简单的情况,其他的条件编译都可以基于这个思想来设计。

例如,在调试程序时,经常希望输出一些需要的信息,但调试完成后不再输出这些信息。 可以将以下条件编译部分插入到源程序中:

#ifdef 调试

打印(“(%p)\n”,文件);

#万一

如果前面有如下命令行:

#调试

程序运行时输出文件指针的值,用于调试和分析。 调试完成后,删除该命令行即可。 可能有人认为,不用条件编译,即调试时添加一批语句,调试完后一条一条删除语句,也能达到这个目的。 确实,这是可能的。 但是,当调试时添加大量语句时,修改的工作量是巨大的。 使用条件编译,您不必将语句一一删除。 只需要删除之前的“#DEBUG”命令即可。 这时,所有使用DEBUG作为标识符的条件编译段都会使其中的语句失效,即统一了“开关”般的控制功能。

有时也采取以下形式:

# 标识符

节目片段1

#别的

节目片段2

#万一

只有第一行与第一种形式不同:将“ifdef”更改为“”。 其作用是:如果标识符未定义,则编译程序段1,否则编译程序段2。这种形式与第一种形式效果相反。

上面两种形式的用法是类似的。 您可以根据自己的需要和便利性选择一种。

还有一种形式,其中 #if 后跟一个表达式而不是简单的标识符:

#if表达式

节目片段1

#别的

节目片段2

#万一

其作用是:当指定的表达式值为真(非零)时,编译程序段1,否则编译程序段2。可以预先给出一定的条件,使程序在不同的条件下执行不同的功能。

例如:输入一行字母,根据需要设置条件编译,可以将所有字母改为大写字母输出,也可以将字母全部改为小写字母输出。

#1

主要的()

char str[20]="C",c;

int i =“0”;

while((c=str[i])!='\0'){

我++;

#如果

if(c>='a'&&c='A'&&c

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码