本文主要介绍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