关于条件编译和预编译的一点学习心得


       项目经验丰富的朋友可能知道,要想让软件可移植性好,代码里面少不了很多的条件编译语句。我最近在移植一个模块时发现了一个我以前不是很懂的东西,那就是条件编译。以前只是知道有这么回事,但具体的细节全然不知。但是每当遇到一个问题,我都会追究到底,不会解决了就放下了。我想这应该是作为一个程序基本的素质吧!下面我简单分享一下我的理解,有不足和遗漏之处,希望大家指正!

        1、条件编译

              请看下面一个例子:

 

#include
#define BB
#ifdef AA
#define HELLO "hello world"
#elif BB
#define HELLO "hello CC"
#endifint main()
{
        printf("%s\n",HELLO);
        return 1;
}


 

        如果你觉得这个打印会是hello CC.那你就和我犯了一样的错误了。如果你用gcc -E hello.c -o hello.i 编译,(这条是预编译命令,下面会讲到。)会出现:error: #if with no expression的错误。原因是BB虽然定义了,但是定义的是空值,放在#elif后面就不行。因为#elif不仅仅是检查后面的宏有没有定义,还会检查其值。但是#ifdef就只是检查后面的宏是否定义,而不管其值为多少。读者可以把#define BB改成#define AA试一下,结果就会打印hello world了。

        读者如果有兴趣,也可以把#define BB改成#define BB   0  试一试,这时用gcc -E hello.c -o hello.i预编译可以编译通过,但是编译过程就不行了,因为#elif   0为假,HELLO没有定义。

 

         2、预编译

        如果你对预编译有过研究,那么下面的内容可能就不适合你了,这里我只是简单的讲讲预编译是怎么回事,不打算也还没能力潜的太深!

        预编译大概有以下内容:

        (1)将以#开头的全部去掉,是宏的就展开,是include的就把源文件内容包含进来

        (2)然后把注释去掉

        (3)添加行号和文件名,以便编译时产生调试信息

        (4)保留所有#pragma编译器指令,因为编译器需要使用它们

        预编译的命令上面已经提到过 :gcc -E 。预编译产生为.i的文件。下面是我预编译后产生hello.i文件的部分内容:

extern char *ctermid (char *__s)__attribute__ ((__nothrow__));

# 820"/usr/include/stdio.h" 3 4

extern void flockfile (FILE*__stream) __attribute__ ((__nothrow__));

 

extern int ftrylockfile (FILE*__stream) __attribute__ ((__nothrow__)) ;

 

extern void funlockfile (FILE*__stream) __attribute__ ((__nothrow__));

# 850"/usr/include/stdio.h" 3 4

# 2 "hello.c" 2

# 11 "hello.c"

int main()

{

 printf("%s\n","helloworld");

 return 1;

}

      有兴趣的朋友可以再深入的研究研究。今天就到这里,欢迎大家提出意见和建议。如果有什么想一起探讨的话题,欢迎大家提出来,我会尽我最大的努力来和你们一起探讨,一起进步。

 

你可能感兴趣的:(LOVE,C)