LPC 语言基础教程:7.3 条件编译

本文节选自《LPC语言基础教程:从零学习游戏开发》,版权归@mudren,欢迎转载,但必须注明来源(mud.ren)。

LPC条件编译的使用和C语言完全相同,主要包括如下:

if...#endif

#if 命令的完整格式为:

#if 整型常量表达式1
    程序段1
#elif 整型常量表达式2
    程序段2
#elif 整型常量表达式3
    程序段3
#else
    程序段4
#endif

#if...#endif指令用于预处理器的条件判断,满足条件时,内部的行会被编译,否则就被编译器忽略。

#if 0
  float pi = 3.1415; // 不会执行
#endif

上面示例中,#if后面的0,表示判断条件不成立。所以,内部的变量定义语句会被编译器忽略。#if 0这种写法常用来当作注释使用,不需要的代码就放在#if 0里面。

#if后面的判断条件,通常是一个表达式。如果表达式的值不等于0,就表示判断条件为真,编译内部的语句;如果表达式的值等于0,表示判断条件为伪,则忽略内部的语句。

#if...#end之间还可以加入#else指令,用于指定判断条件不成立时,需要编译的语句。

#define FOO 1

#if FOO
  printf("defined\n");
#else
  printf("not defined\n");
#endif

上面示例中,宏FOO如果定义过,会被替换成1,从而输出defined,否则输出not defined

如果有多个判断条件,还可以加入#elif命令。

#if HAPPY_FACTOR == 0
  printf("I'm not happy!\n");
#elif HAPPY_FACTOR == 1
  printf("I'm just regular\n");
#else
  printf("I'm extra happy!\n");
#endif

上面示例中,通过#elif指定了第二重判断。注意,#elif的位置必须在#else之前。如果多个判断条件皆不满足,则执行#else的部分。

没有定义过的宏,等同于0。因此如果UNDEFINED是一个没有定义过的宏,那么#if UNDEFINED为伪,而#if !UNDEFINED为真。

#if的常见应用就是打开(或关闭)调试模式。

#define DEBUG 1

#if DEBUG
printf("value of i : %d\n", i);
printf("value of j : %d\n", j);
#endif

上面示例中,通过将DEBUG设为1,就打开了调试模式,可以输出调试信息。

在LPC中有一个特殊的预编译判断函数efun_defined,可以判断指定efun是否定义,如:

#if efun_defined(parse_command)
    // todo
#else
    // todo
#endif

ifdef...#endif

#ifdef 命令的格式为:

#ifdef  宏名
    程序段1
#else
    程序段2
#endif

#ifdef...#endif指令用于判断某个宏是否定义过。

有时源码文件可能会重复包含某个库,为了避免这种情况,可以在库文件里使用#define定义一个空的宏。通过这个宏,判断库文件是否被包含了。

#define EXTRA_HAPPY

上面示例中,EXTRA_HAPPY就是一个空的宏。

然后,源码文件使用#ifdef...#endif检查这个宏是否定义过。

#ifdef EXTRA_HAPPY
  printf("I'm extra happy!\n");
#endif

上面示例中,#ifdef检查宏EXTRA_HAPPY是否定义过。如果已经存在,表示加载过库文件,就会打印一行提示。

#ifdef可以与#else指令配合使用。

#ifdef EXTRA_HAPPY
  printf("I'm extra happy!\n");
#else
  printf("I'm just regular\n");
#endif

上面示例中,如果宏EXTRA_HAPPY没有定义过,就会执行#else的部分。

#ifdef...#else...#endif可以用来实现条件加载。

#ifdef MAVIS
  #include "foo.h"
  #define STABLES 1
#else
  #include "bar.h"
  #define STABLES 2
#endif

上面示例中,通过判断宏MAVIS是否定义过,实现加载不同的头文件。

ifndef...#endif

#ifndef 命令的格式为:

#ifndef 宏名
    程序段1
#else
    程序段2
#endif

#ifndef...#endif指令跟#ifdef...#endif正好相反。它用来判断,如果某个宏没有被定义过,则执行指定的操作。

#ifdef EXTRA_HAPPY
  printf("I'm extra happy!\n");
#endif

#ifndef EXTRA_HAPPY
  printf("I'm just regular\n");
#endif

上面示例中,针对宏EXTRA_HAPPY是否被定义过,#ifdef#ifndef分别指定了两种情况各自需要编译的代码。

#ifndef常用于防止重复包含。举例来说,为了防止头文件myheader.h被重复包含,可以把它放在#ifndef...#endif里面包含。

#ifndef MYHEADER_H
#define MYHEADER_H
#include "myheader.h"
#endif

上面示例中,宏MYHEADER_H对应文件名myheader.h的大写。只要#ifndef发现这个宏没有被定义过,就说明该头文件没有包含过,从而加载内部的代码,并会定义宏MYHEADER_H,防止被再次加载。

在LPC编程中,推荐使用#ifndef防止头文件报重复定义的警告,如:

#ifndef ANSI_H
#define ANSI_H

// 定义头文件

#endif

推荐把所有头文件都以这种方式定义,注意定义的宏不要重名就好。

注意在LPC语言中没有 defined 预处理

// 示例:7.3.1
#define X 11

int main(object me, string arg)
{
#ifdef FLUFFOS
    debug("driver 是 FLUFFOS!");
#else
    #ifdef MUDOS
        debug("driver 是 MUDOS!");
    #else
        debug("未知 driver!");
    #endif
#endif

#if X < 1 || X > 10
    debug("X = " + X);
#else
    debug("...");
#endif

#ifdef __PACKAGE_DB__
    debug("支持数据库!");
#endif

    return 1;
}
京ICP备13031296号-4