结合我自己的经验,谈一谈模块化编程时#include应该出现的位置。总结起来大体有二条规则:

一、规则1:只包含必要的头文件

  看下面这个模块:

===foo.c====
#include <stdio.h>
#include <foo.h>
#include <uart.h>
void foo ()
{
printf ("hello world!\n");
}
===foo.h====
#ifndef __foo_h__
#define __foo_h__ extern void foo(); #endif

在foo()函数中也只有简单的一行打印语句。由于printf()函数的原型声明来源于stdio.h,因此foo.c中包含了stdio.h无可厚非,否则根本无法使用。但foo.c文件中除了包含stdio.h外还包含了另外一个多余的头文件 ——uart.h,这不会导致编译的出错,但我们并不需要使用uart.h中声明的接口,因此这种行为会导致编译效率的降低。如果此时uart.h中还包含了其它文件,那么全部都会在预处理时展开到foo.c中。当一个项目的代码量很大时,由于效率地下而多占用的时间就无法忽视了。

二、规则2:使#include出现在它被需要的地方

为了使用printf()函数,可以把#include<stdio.h>放在foo.h文件中,编译也可以正常通过,如下:

===foo.h====
#ifndef __foo_h__
#define __foo_h__ #include <stdio.h> extern void foo(); #endif
===foo.c====

#include <foo.h>

void foo ()
{
printf ("hello world!\n");
}

但这样会产生一个问题,stdio.h对于我们的头文件foo.h来说,是必须的么?当然不是!那么会导致什么样的问题呢?我们已经直到.h文件的作用相当于模块的使用说明书,如果其它模块要使用foo模块时,需要通过#include<foo.h>来添加接口函数,此时就会间接的包含了stdio.h,同样的会导编译致速度下降的问题。因此,正确的做法是将#include<stdio.h>放在foo.c中,如下:

===foo.h====
#ifndef __foo_h__
#define __foo_h__ extern void foo(); #endif ===foo.c====
#include <stdio.h>
#include <foo.h> void foo ()
{
printf ("hello world!\n");
}

理解了上面的例子,则看下面一条实例:

在system.h中,定义了如下结构体定义:

=====system.h=====

#ifndef __system_h__
#def __system_h__ typedef struct stuTAG{ char * name;
u8 age; }stu_st; #endif

同样在一个foo.c模块中,定义了一个函数:

===foo.h====
#ifndef __foo_h__
#define __foo_h__
#include "system.h" extern void print_info(stu_st * student); #endif
=====foo.c=====
#include "foo.h"
#include <stdio.h> void print_info(stu_st * student)
{
printf("name:%s\n",student->name);
printf("age :%d\n",student->age); }

从这个foo模块的实现代码来看,foo.h和foo.c都需要了解stu_st结构体的内容,也就是stu_st是被foo.c和foo.h同时需要的,因此它必须被放置在foo.h中,否则编译时会出现stu_st未定义的错误,此时将#include放置在.h文件中是必须的!

用一句话概括:只在必要的地方包含必要的头文件!

模块化编程时,#include到底要放在哪里?的更多相关文章

  1. keil采用C语言模块化编程时全局变量、结构体的定义、声明以及头文件包含的处理方法

    以前写单片机程序时总是把所用函数和变量都写在一个c文件里,后来遇到大点的项目,程序动则几千行,这种方式无疑会带来N多麻烦,相信大家都有所体验吧! 后来学会了在keil里进行模块化编程,即只把功能相同或 ...

  2. 详解keil采用C语言模块化编程时全局变量、结构体的定义、声明以及头文件包含的处理方法

    一.关于全局变量的定义.声明.引用: (只要是在.h文件中定义的变量,然后在main.c中包含该.h文件,那么定义的变量就可以在main函数中作为全局变量使用) 方法1: 在某个c文件里定义全局变量后 ...

  3. 【C语言探索之旅】 第二部分第一课:模块化编程

    内容简介 1.课程大纲 2.第二部分第一课: 模块化编程 3.第二部分第二课预告: 进击的指针,C语言王牌 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C ...

  4. 单片机 C 语言模块化编程

    好的开始是成功的一半 通过上一章的学习,我想你已经掌握了如何在程序中释放CPU了.希望能够继续坚持下去.一个良好的开始是成功的一半.我们今天所做的一切都是为了在单片机编程上做的更好. 在谈论今天的主题 ...

  5. 嵌入式C语言之---模块化编程

    当你在一个项目小组做一个相对较复杂的工程时,意味着你不再独自单干.你需要和你的小组成员分工合作,一起完成项目,这就要求小组成员各自负责一部分工程.比如你可能只是负责通讯或者显示这一块.这个时候,你就应 ...

  6. js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写 ...

  7. [转]js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    原文: https://www.cnblogs.com/chenguangliang/p/5856701.html ------------------------------------------ ...

  8. Javascript模块化编程(三):require.js的用法

    Javascript模块化编程(三):require.js的用法 原文地址:http://www.ruanyifeng.com/blog/2012/11/require_js.html 作者: 阮一峰 ...

  9. Javascript模块化编程之路——(require.js)

    转自:http://www.ruanyifeng.com/blog/2012/10/javascript_module.html Javascript模块化编程(一):模块的写法 随着网站逐渐变成&q ...

随机推荐

  1. C#中页面之间跳转方法比较

    一直以来,各种跳转方法混用,浑浑噩噩没有仔细去了解过每个跳转方法的区别 1.<a herf="default.asp"></a>  超链接跳转 2.< ...

  2. html EVENT对象

    Event 对象 Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 事件通常与函数结合使用,函数不会在事件发生前被执行! onabort 图像的加 ...

  3. PHP Date()函数详细参数

    在页面的最前页加上 date_default_timezone_set(PRC); /*把时间调到北京时间,php5默认为格林威治标准时间*/ date () a: "am"或是& ...

  4. Linux下的网卡驱动程序的编写过程(转)

    工作需要写了我们公司一块网卡的linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大家的喜爱.真希望她能在中国迅速成长.把程序文档贴出来,希 ...

  5. 《C专家编程》第四章——令人震惊的事实:数组和指针并不相同

    数组和指针是C语言里相当重要的两部分内容,也是新手程序员最容易搞混的两个地方,本章我们锁定指针与数组,探讨它们的异同点. 首先来看指针与数组在声明上的区别: int a[10]; int *p; 很明 ...

  6. CI框架 CodeIgniter 伪静态 htaccess设置和Nginx伪静态方法2

    1.在根目录西下  新建.htaccess 文件 RewriteEngine on RewriteCond $1 !^(index\.php|images|robots\.txt) RewriteRu ...

  7. css伪类选择器及伪元素选择器

    1.类选择器 在css中可以使用类选择器把相同的元素定义成不同的样式.比如: 结果如下: 标题背景未变 2.伪类选择器 类选择器和伪类选择器的区别在于,类选择器我们定义的,而伪类选择器是CSS中已经定 ...

  8. 注册noip.com动态域名的步骤

    1.先打开这个网址 http://www.noip.com/ 2.点击页面右上绿色的Sing Up,进行注册 3.会出现这个页面,把这些填上 Create my hostname later这一项不打 ...

  9. vm centos 网络配置

    安装Centos系统,查看网络配置. 输入命令:ifconfig 127.0.0.1 要开启网络 进入ifcfg-eth0文件. 输入命令:vi /etc/sysconfig/network-scri ...

  10. 转-Spring Framework中的AOP之around通知

    Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: spring ...