您的位置:首页 > 其它

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

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

1、条件编译

请看下面一个例子:

#include<stdio.h>
#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;
}
有兴趣的朋友可以再深入的研究研究。今天就到这里,欢迎大家提出意见和建议。如果有什么想一起探讨的话题,欢迎大家提出来,我会尽我最大的努力来和你们一起探讨,一起进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: