【编程好习惯】永远将头文件作为定义和引用的桥梁
在现实项目中,有时为了省事在引用一个变量或函数时,会直接采用extern关键定在.c文件中进行声明。图1中reference.c的第3行是对一个变量采用extern关键字进行声明,图2中reference.c的第1行则是对一个函数采用extern关键字进行声明。
define.c
00001: char g_name [] = {’Y’, ’u’, ’n’, ’\0’};
reference.c
00001: #include <stdio.h>
00002:
00003: extern char *g_name;
00004:
00005: int main ()
00006: {
00007: printf ("%c\n", g_name [0]);
00008: return 0;
00009: }
图1
define.c
00001: #include <stdio.h>
00002:
00003: void foo (const char *_p_arg1, const char *_p_arg2)
00004: {
00005: printf ("%s,%s\n", _p_arg1, _p_arg2);
00006: }
reference.c
00001: extern void foo (int, const char *_p_arg);
00002:
00003: int main ()
00004: {
00005: foo (-1, "Haha!");
00006: return 0;
00007: }
图2
通过使用图3所示的命令分别编译图1和图2中的代码并运行之,读者将发现两个程序都将出现崩溃的结果。其原因就是变量的真实定义与被引用时的声明出现了不匹配,《混淆指针和数组所导致的错误》一文对这类问题进行了分析,以及解释了为什么编译器发现不了这类问题。
yunli.blog.51cto.com~
$gcc -g define.c reference.c -o example.exe
图3
为了杜绝类似事情的发生,需要通过使用头文件来作为变量或是函数的定义和引用的桥梁。图4和图5是分别采用头文件的实现方式。两个实现各自都定义了一个define.h头文件用于声明变量或是函数的原型,接着在define.c和reference.c中都包含这一头文件。如果采用图3所示的命令再一次编译两个程序,些时编译器将报错。
define.h
00001: extern char *g_name;
define.c
00001: #include ”define.h”
00002:
00003: char g_name [] = {’Y’, ’u’, ’n’, ’\0’};
reference.c
00001: #include <stdio.h>
00002: #include ”define.h”
00003:
00004: int main ()
00005: {
00006: printf ("%c\n", g_name [0]);
00007: return 0;
图4
define.h
00001: extern void foo (int, const char *_p_arg);
define.c
00001: #include <stdio.h>
00002: #include ”define.h”
00003:
00004: void foo (const char *_p_arg1, const char *_p_arg2)
00005: {
00006: printf ("%s,%s\n", _p_arg1, _p_arg2);
00007: }
reference.c
00001: #include ”define.h”
00002:
00003: int main ()
00004: {
00005: foo (-1, "Haha!");
00006: return 0;
00007: }
图5
在项目中之所以会出现直接采用extern进行外部变量或函数的引用,无非存在两种原因。其一是图省事;其二则是由于项目中的头文件规划得太乱,以至于要包含一个头文件会引入更多其它没完没了的头文件需要包含,当然其本质还是图省事。要使得项目组做到永远采用将头文件作为定义和引用的桥梁,必须做到整个项目中的头文件都组织得可以被方便的包含,而要做到这一点,必须运用《精确包含头文件》这一编程好习惯。
本文出自 “至简李云” 博客,请务必保留此出处http://yunli.blog.51cto.com/831344/291475
相关新闻>>
- 发表评论
-
- 最新评论 更多>>