行业知识
C/C++条件编译:#ifdef、#else、#endif等
文章目录
- #undef指令
- 从C预处理器角度看已定义
- 条件编译
- 1.#ifdef、#else和#endif指令
- #ifndef指令
- #ifndef指令通常用于防止多次包含一个文件
- 程序使用#ifndef避免文件被重复包含
- #if和#elif指令
- 条件编译还有一个用途是让程序更容易移植
- 参考
程序员可能要为不同的工作环境准备C程序和C库包。不同的环境可能
使用不同的代码类型。预处理器提供一些指令,程序员通过修改#define的值
即可生成可移植的代码。#undef指令取消之前的#define定义。#if、#ifdef、
#ifndef、#else、#elif和#endif指令用于指定什么情况下编写哪些代码。#line
指令用于重置行和文件信息,#error指令用于给出错误消息,#pragma指令用
于向编译器发出指令。
#undef指令
#undef指令用于“取消”已定义的#define指令。也就是说,假设有如下定义:
#define LIMIT 400
然后,下面的指令:
#undef LIMIT
将移除上面的定义。现在就可以把LIMIT重新定义为一个新值。即使原
来没有定义LIMIT,取消LIMIT的定义仍然有效。如果想使用一个名称,又
不确定之前是否已经用过,为安全起见,可以用#undef 指令取消该名字的定
义。
从C预处理器角度看已定义
处理器在识别标识符时,遵循与C相同的规则:标识符可以由大写字
母、小写字母、数字和下划线字符组成,且首字符不能是数字。当预处理器
在预处理器指令中发现一个标识符时,它会把该标识符当作已定义的或未定
义的。这里的已定义表示由预处理器定义。如果标识符是同一个文件中由前
面的#define指令创建的宏名,而且没有用#undef 指令关闭,那么该标识符是
已定义的。如果标识符不是宏,假设是一个文件作用域的C变量,那么该标
识符对预处理器而言就是未定义的。
已定义宏可以是对象宏,包括空宏或类函数宏:
#define LIMIT 1000 // LIMIT是已定义的#define GOOD // GOOD 是已定义的#define A(X) ((-(X))*(X)) // A 是已定义的int q; // q 不是宏,因此是未定义的#undef GOOD // GOOD 取消定义,是未定义的
注意,#define宏的作用域从它在文件中的声明处开始,直到用#undef指
令取消宏为止,或延伸至文件尾(以二者中先满足的条件作为宏作用域的结
束)。
另外还要注意,如果宏通过头文件引入,那么#define在文件中的位置
取决于#include指令的位置。
稍后将介绍几个预定义宏,如__DATE__和__FILE__。这些宏一定是已
定义的,而且不能取消定义。
条件编译
可以使用其他指令创建条件编译(conditinal compilation)。也就是说,
可以使用这些指令告诉编译器根据编译时的条件执行或忽略信息(或代码)
块。
1.#ifdef、#else和#endif指令
我们用一个简短的示例来演示条件编译的情况。考虑下面的代码:
#ifdef MAVIS#include "horse.h"// 如果已经用#define定义了 MAVIS,则执行下面的指令#define STABLES 5#else#include "cow.h" //如果没有用#define定义 MAVIS,则执行下面的指令#define STABLES 15#endif
这里使用的较新的编译器和 ANSI 标准支持的缩进格式。如果使用旧的
编译器,必须左对齐所有的指令或至少左对齐#号,如下所示:
#ifdef MAVIS#include "horse.h" // 如果已经用#define定义了 MAVIS,则执行下面的指令#define STABLES 5#else#include "cow.h" //如果没有用#define定义 MAVIS,则执行下面的指令#define STABLES 15#endif
#ifdef指令说明,如果预处理器已定义了后面的标识符(MAVIS),则
执行#else或#endif指令之前的所有指令并编译所有C代码(先出现哪个指令
就执行到哪里)。如果预处理器未定义MAVIS,且有 #else指令,则执行
#else和#endif指令之间的所有代码。
#ifdef #else很像C的if else。两者的主要区别是,预处理器不识别用于标
记块的花括号({}),因此它使用#else(如果需要)和#endif(必须存在)
来标记指令块。这些指令结构可以嵌套。也可以用这些指令标记C语句块
ifdef.c程序
/* ifdef.c -- 使用条件编译 */#include #define JUST_CHECKING#define LIMIT 4int main(void){int i;int total = 0;for (i = 1; i total += 2 * i*i + 1;#ifdef JUST_CHECKINGprintf("i=%d, running total = %d\n", i, total);#endif}printf("Grand total = %d\n", total);return 0;}char first[SLEN];char last[SLEN];};// 类型定义typedef struct names_st names;// 函数原型void get_names(names *);void show_names(const names *);char * s_gets(char * st, int n);#endifnames winner = { "Less", "Ismoor" };printf("The winner is %s %s.\n", winner.first,winner.last);return 0;}
上一篇:mc正版怎么做服务器?
下一篇:数据结构:5