概述

C语言程序从源文件经过编译、链接生成可执行文件。那么编译与链接分别做了什么? 开发中为什么使用.h编写函数的声明?接下来使用案例说清楚为什么这样编写代码。

C语言程序的编译和链接

C语言程序从源文件到生成可执行程序需要经过编译器的预处理,汇编、编译、链接。这里简化为编译、链接两个阶段

编译:对源文件语法做检查

链接:会查找函数的具体实现并把项目中所有相关的.o目标文件、C语言函数库合并在一起生成可执行文件

我来编写一个main.c

对main.c进行编译,可以用clang或者gcc编译器都可以

$gcc -c main.c
$clang -c main.c

一旦执行编译你会发现,编译通过了,编译器只是提示一个警告

警告只是告诉main.c调用sum函数没有函数声明,那我们添加sum函数声明再次编译

perfect!编译完美通过,生成目标文件main.o

接着问题就来了,mian.c根本就没有sum函数定义,怎么就可以编译通过呢? 编译只是检查语法,main.c中调用sum函数并且有函数声明就没有语法问题,编译自然可以通过。

接下来你想生成可执行程序还差一步链接的操作

$gcc main.o -o main
$clang main.o -o main

报错是因为找不到main.c中的调用sum函数的定义,链接失败。 由此证明链接会查找该文件调用所有函数的定义

这次就完美了,可以编译器、链接一起来

$gcc main.c -o main
$clang main.c -o main

编译链接通过,输出执行结果21

C语言多文件开发

上面main.c调用了函数sum,在企业开发中是分文件开发,现在模拟一个场景。

A负责编写main.c, B负责编写Math.c(数学运算的一些函数)提供给A调用。

$ gcc -c main.c Math.c
$ gcc main.o Math.o -o app

执行程序app运行成功!

虽然A与B这样配合可以完成项目开发,但是会发现A调用B中的函数,需要去B的Math.c中找函数定义,并将在main.c中手动添加该函数的声明。这样做法是不合理的,Math.c是由B写的,B对它最熟悉的,对于调用者不需要这么麻烦,因此.h文件的作用就诞生了!

B除了编写Math.c,还要维护一个.h文件,将Math.c可以供外界调用的函数声明写在.h中。这样A在调用只需要在main.c中包含Math.h文件即可。即使以后B的Math.c中新增加了函数,A不需要修改代码,查看Math.h有这个函数声明直接调用就可以了。

.h文件作用是被其它文件包含,是不参与编译的。

窥探C语言程序的编译、链接与.h文件的更多相关文章

  1. C语言程序经过编译链接后形成二进制映像文件的组成

    C语言程序经过编译链接后形成二进制映像文件由栈,堆,数据段,代码段组成,其中数据段又分为:只读数据段,已经初始化读写数据段,未初始化数据段(BSS段).如下图所示: 1.栈区(stack):由编译器自 ...

  2. 13_传智播客iOS视频教程_OC程序的编译链接

    C程序的编译.链接.执行怎么来的?在.C文件里面写上符合C语言部分的源代码.OC也是一样的.记住:OC程序的后缀名是.m. 为什么要链接?第一个.o的目标文件里面它启动不了.因为它没有启动代码我们要加 ...

  3. iOS_02_第一个C语言程序(理解编译、连接、运行)

    一.开发工具的选择 1. 可以用来写代码的工具:记事本.ULtraEdit.Vim.Xcode等. 2. 选择XCode的原因:苹果公司官方提供的开发利器.简化开发的工程.有高亮显示功能. 3. 使用 ...

  4. 读书笔记-详解C程序开发中 .c和.h文件的区别

    一个简单的问题:.c和.h文件的区别 学了几个月的C语言,反而觉得越来越不懂了.同样是子程序,可以定义在.c文件中,也可以定义在.h文件中,那这两个文件到底在用法上有什么区别呢? 2楼: 子程序不要定 ...

  5. Ubuntu下编译C语言程序(同时给编译生成的文件命名)

    1.创建c文件 test.c touch test.c 2.编写test.c vim test.c #include "stdio.h" int main(){ printf(&q ...

  6. 通过终端编译链接运行C文件

    1.创建c文件 touch demo.c 2.编辑c代码 3.编译(预编译.检查语法.编译).链接 3.1.指令:cc  -c  demo.c 正常情况下,会生成一个demo.o的二进制文件(即:目标 ...

  7. 计算机二级-C语言-程序填空题-190117记录-对文件的处理,复制两个文件,往新文件中写入数据。

    //给定程序的功能是,调用函数fun将指定源文件中的内容赋值到指定目标文件中,复制成功时函数返回1,失败时返回0,把复制的内容输出到终端屏幕.主函数中源文件名放在变量sfname中,目标文件名放在变量 ...

  8. Linux C程序的编译过程

    Linux C程序的编译过程 学习一门语言程序,本人觉得还是得学习它的编译规则,现在,通过小例子小结下自己对C编译的认识. /*test.c     了解C程序的编译*/ #include <s ...

  9. [转]C++编译链接过程详解

    C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接.编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程.链接是把目标文件.操作 ...

随机推荐

  1. 42 github 开源代码 ——README.md语法/相关操作等

    0 引言 最近在github上开源了pro/E二次开发的代码,发现README.md的编辑方式很有趣,需要稍微了解一下. 1 markdown语法 参考了两篇博客的内容,链接如下. https://b ...

  2. NX二次开发-UFUN输入表达式名称,获取它的名称和值UF_MODL_ask_exp

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> UF_initialize(); //创建一个新的表达式,有TAG tag_t ...

  3. Photon Server的服务器端配置

    Photon Server与Unity3D的交互分为3篇博文实现 (1)Photon Server的服务器端配置 (2)Photon Server的Unity3D客户端配置 (3)Photon Ser ...

  4. 3步永久性激活IntelliJ IDEA 亲测有效

    1.进到文件夹中:C:\Windows\System32\drivers\etc ,找到hosts文件,用文本编辑器打开文件,将“  0.0.0.0 account.jetbrains.com ”添加 ...

  5. 如何理解CUDA中的cudaMalloc()的参数

    首先看下此运行时函数的原型: cudaError_t cudaMalloc (void **devPtr, size_t size ); 主要的第一个参数.为什么是两个星星呢?用个例子来说明下. fl ...

  6. 消息中间件kafka学习记录

    目录 1. 概述 2. 环境准备 3. 命令行常用命令 4. java api实现 1. 概述 Apache Kafka是一个分布式消息系统,凭借其优异的特性而被广泛使用. 高性能:O(1)复杂度消息 ...

  7. hbase 集群搭建(公司内部测试集群)

    我用的是cdh4.5版本:配置文件:$HBASE_HOME/conf/hbase-env.shexport JAVA_HOME=$JAVA_HOMEexport JAVA_HOME=/home/had ...

  8. Python 执行tail文件并操作

    def log_search(self, logfile, search_content, timeout=10): import time import subprocess import sele ...

  9. Spark中的各种action算子操作(java版)

    在我看来,Spark编程中的action算子的作用就像一个触发器,用来触发之前的transformation算子.transformation操作具有懒加载的特性,你定义完操作之后并不会立即加载,只有 ...

  10. iOS 工程实现native 跳转指定的Flutter 页面

    概要 在前一篇文章中我们提到,iOS跳转到Flutter工程指定页面时(多个),Flutter只有单例,设置setInitialRouter 无效,如下 let flutterViewControll ...