Introduction

代码要实现比较复杂的功能时,往往会包含非常多的函数。
当我们想再向其中添加其他功能或修改一些功能时,主程序所在的源代码会越来越冗长,查找并准确地修改某功能对应的函数也变得十分困难。
这时候我们不禁希望拥有一个干净简洁的主程序,就像大树的枝干,把每一个“分支”(即不同的功能模块)集成到一个专门的源代码文件中,方便查找和修改;需要添加全新功能时,写一个新的文件包含进主程序文件即可。


下面以经典Hello wolrd为例,简要阐明如何实现这一想法 —— 在主程序中引用外部源代码中的函数。

Method

  • 先写一个常规的 hello world,并且编译运行它:
touch hello.c //linux下终端创建源代码文件

hello.c 中写入

#include <stdio.h>
int main(void)
{printf("Hello World!\n");return 0;
}

gcc 命令编译为hello文件,然后 ./ 运行一下

Well done!

  • 接下来,我们试图把输出“Hello world!”的这个功能封装到一个名为Hello的函数中,并且把这个函数给移到别的文件
    此时我们想要的主程序代码是这样的:
#include <stdio.h>
int main(void)
{   Hello();return 0;
}

其中,这个Hello函数定义应该是这样:

void Hello(void)
{printf("Hello world again!"); #为了区别于第一次的输出,这里加了again
}

可是怎么才能跨文件调用这个Hello函数呢?

  • C语言中,使用函数通常需要经过 声明定义引用,外部文件中的函数也不例外。
    所以我们首先在同一个目录下再创建另外两个文件:
touch  declaration.h  functions.c  //这是linux下的终端操作

我们现在有三个文件了:
- hello.c 主程序所在的源文件(大树的“树干”,作用是引用
- declaration.h 专门用于声明函数的头文件(最好起个更短的名字 )
- functions.c 定义函数的源文件(大树的“分支”)

  • 写函数声明和定义
  1. declaration.h声明函数Hello
void Hello(void);
Tips:*此后每新加一个函数,就在该声明头文件中添一行即可*
  1. functions.c定义函数Hello
void Hello() #函数类型和参数都为空,要和声明对应一致
{printf("Hello world again!");
}
  1. hello.c使用/引用函数Hello
#include <stdio.h>
#include "declaration.h"  #在主函数开始前添加包含函数声明的头文件 declaration.h
int main(void)
{   Hello();  #试图调用的外部函数return 0;
}
#include "functions.c"  #包含函数定义的外部文件 functions.c
Tips:  #include < > 是从C语言标准库中查找头文件;#include " " 是从源代码所在目录中查找头文件,一般自己编写的头文件用引号。

引用要比声明和定义略显复杂,需要使用两个#include,用于包含声明函数的头文件,和定义函数的.c文件需要特别注意的是,声明头文件必须放在main函数前面,不然会报错找不到这个函数!

  • 运行一下试试看!

    Well done!

现在我们已经知道怎么正确地在主程序中引用外部函数了,但实际应用中我们势必面临更多类型的函数,就算没多复杂,它至少会有那么几个变量。
所以我们想知道,跨文件函数中的变量要怎么定义呢?
——答案很简单,和不跨文件的一模一样!

Further example

下面的例子声明了两个变量,数组a[]在主函数外(相当于全局变量),b[]在主函数内(只在主函数内有效的局部变量)。

#include <stdio.h>
#include "declaration.h"
char a[20] = "Hello wolrd A!";  #相当于全局变量
int main(void)
{char b[20] = "Hello wolrd B!";  #相当于局部变量Hello();return 0;
}
#include "functions.c"

我们在外部函数Hello中使用这两个变量看看效果:

void Hello()
{printf(a);printf(b);printf("Hello world again!\n");
}

编译运行一下:

运行结果告诉我们,变量b没有声明(undeclared),不能使用。

  • 把变量b也放在main函数前面就可以使用了:

hello.c

#include <stdio.h>
#include "declaration.h"
char a[20] = "Hello wolrd A!";  #相当于全局变量
char b[20] = "Hello wolrd B!";  #相当于全局变量
int main(void)
{Hello();return 0;
}
#include "functions.c"

function.c

void Hello()
{printf(a);printf(b);printf("Hello world again!\n");
}

编译运行:

  • 事实上,使用 #include 包含外部函数文件相当于在主程序后面“续”上一段代码,大可合起来看作一个源代码。
  • 所以,在外部函数中改变全局变量a,b的值会导致主程序中变量值的改变,新手应当注意这一点,以避免一些不易发现的错误。
  • 我们试试:
    hello.c
#include <stdio.h>
#include <string.h>  #使用字符串数组函数时需要的头函数
#include "declaration.h"
char a[20] = "Hello wolrd!";  #相当于全局变量
int main(void)
{printf(a);Hello();printf(a);return 0;
}
#include "functions.c"

function.c

void Hello()
{printf(a);strcpy(a, "Goodnight world!\n"); #使用字符串copy函数,给数组a重新赋值printf(a);
}
  • 结果会是什么呢?

Completely done !

现在你已经学会怎么修剪打理“程序树”的枝干了,开始真正的编程工作吧!

C语言主程序如何引用外部源代码中的函数相关推荐

  1. c语言非静态成员引用方式,C++中静态成员函数访问非静态成员的实例

    C++中静态成员函数访问非静态成员的实例 实现代码: #include /* 静态成员函数只能访问静态数据成员.静态成员函数和类以外的函数和数据,不能访问非静态数据成员,但静态成员函数或静态数据成员可 ...

  2. WPF引用外部类库中的资源文件提示不能找到的解决方法

    WPF引用外部类库中的资源文件提示不能找到的解决方法 参考文章: (1)WPF引用外部类库中的资源文件提示不能找到的解决方法 (2)https://www.cnblogs.com/scy251147/ ...

  3. C语言beep中有什么作用,C++中发声函数Beep用法

    当我们听到电脑上出现美妙的旋律的时候,是不是发现这是一个很伟大的开发,这就是C语言中Beep,下面爱站技术频道小编就给大家介绍C++中发声函数Beep用法. 下面是正文: •其实啊,Windows A ...

  4. 《TensorFlow 实战》第五章源码 5.2 源代码中权重函数中初始化函数 tf.truncated_normal(shape, stddev=0.1) 中 stddev 的重要性

    <TensorFlow 实战>黄文坚  黄源著 源码地址:https://github.com/sundaygeek/tensorflow-in-action/blob/master/5_ ...

  5. 调用外部 DLL 中的函数(显示调用)

    unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Di ...

  6. r语言写内曼最优分配_R中最优化函数optim

    最优化函数optim 目标函数: $$f(x_1,x_2)=(1-x_1)^2+100(x_2-x_1^2)^2$$ 该函数全局最小值在($x_1=1,x_2=1$)时取到. 下面这种写法是因为有多个 ...

  7. Angular7中引用外部JS文件

    Angular7中引用外部JS文件,步骤如下: 1. 将引入的js文件放到项目的src/assets下 2. 在angular.json文件中找到scripts项并配置js文件的相对路径 3. 在sr ...

  8. 页面中如何引用外部的HTML(四种方法)

    页面中如何引用外部的HTML(四种方法) 一.总结 一句话总结:a.iframe标签        b.ajax引入代码片段        c.link import的方法导入        d.re ...

  9. 【C 语言】动态库封装与设计 ( 动态库调用环境搭建 | 创建应用 | 拷贝动态库相关文件到源码路径 | 导入头文件 | 配置动态库引用 | 调用动态库中的函数 )

    文章目录 一.在 Visual Studio 2019 中创建 " 控制台应用 " 程序 二.拷贝 xxx.lib.xxx.dll.xxx.h 到源码路径 三.导入 xxx.h 头 ...

最新文章

  1. idea设置开发方式
  2. java中hashCode()在Map中的作用
  3. OEA 框架演示 - 快过原型的开发
  4. python定义一个空数组_python如何创建空数组?
  5. php try catch
  6. 关于 mysql.test 数据库
  7. java后端怎么返回音频流_Java语言中的IO流read()方法返回值为什么是int而不是byte?...
  8. 文字生成视频,只需一步
  9. 自动运维化tools篇2:通过SSH信任关系,批量修改LINUX密码
  10. Keil(MDK) 5 软件安装教程
  11. 腾讯智图让我的webp压缩感觉像白忙活一样
  12. 几种不同的json格式解析
  13. 电商平台10大商业与盈利模式
  14. C相关笔试题或者面试题中的概念以及技巧题2
  15. 一文搞懂天使轮、A轮、B轮、C轮、D轮融资
  16. 手机处理器天梯图2021
  17. 神经网络实现手写数字识别
  18. android之基于百度语音合讯飞语音识别的语音交互
  19. 火车头采集器V10下载-火车头采集器免费
  20. VAPS XT开发入门教程02:安装配置

热门文章

  1. Linux在线安装MySQL
  2. java设置右击菜单_windows7中右键菜单添加powershell
  3. Matlab/simulink MIL自动化测试工具使用说明
  4. 强势来袭!取代传统PC开辟新增长极,这款“云电脑”凭啥?
  5. atom编辑器的常用插件
  6. 计算机硬件闫宏印答案,计算机硬件技术基础
  7. System.Diagnostics.Process 用处
  8. 智慧农业“黑科技”,FCU1101智能灌溉控制器方案
  9. 海康摄像头与萤石云web集成记录
  10. 迎接全电发票的管理方式,iBox电子会计档案管理系统