简单理解C语言如何构建工程

首先我们最好有一个好用的编辑器,vscode也好,visual studio也罢,dev也行,这里我们使用的是code::block;

一、了解C语言工程的构建原理

​ 首先我在这里放一张图,让我们来看一下是这张图叙述了那些事情:

​ 上图取自大名鼎鼎的csapp,它描述了一个C语言程序出生的步骤,我们在编译器中写好程序按下“构建”(或者编译或者make)按钮,最先作用的是预处理器,预处理器根据头文件把该连接的源文件连接到一起,然后准备编译,编译的过程是词法分析的过程,经过词法分析之后,程序编译成了汇编程序,如果我们打开汇编程序,我们会看到一系列寄存器操作,汇编语言是非常底层的语言,再之后汇编语言经过汇编就变成了*.o文件,o文件经过链接,就变成了可执行的、二进制的目标文件

​ 下面呢,我们再来介绍一个东西,它叫做makefile,makefile呢,是gnu出品的自动化构建工程的工具,使用make命令就可以调用执行make文件(linux一切皆文件的思想嘛),make文件会根据当前目录下的makefile文件(没有后缀)来执行一系列终端命令,从而代替手工来完成程序的编译操作

[注]:如果你的工具链是mingw,那么相应的命令将是mingw32-make,你可以去工具链的安装目录中找一下这个程序(这个程序就叫mingw32-make)

​ 下面我们来介绍一个makefile的例子,

main:main.o abc.o xyz.o
gcc main.o abc.o xyz.o -o main
main.o:main.c abc.h xyz.h
gcc -c main.c –o main.o -g
abc.o:abc.c abc.h xyz.h
gcc -c abc.c –o abc.o -g
xyz.o:xyz.c xyz.h
gcc -c xyz.c -o xyz.o -g
clean:
rm main main.o abc.o xyz.o -f

​ 那么我们为什么要来介绍这个例子呢?我们重点看的是第一行,也就是上面那个”C程序的出生“中链接的部分:真正生成一个C工程,我们需要不同的源文件生成o文件之后,最终链接到一起,也就是这个例子中,你要生成名为main的可执行文件(exe也好,其他的也好),总之你需要三个o文件,

​ 上面我们介绍了编译汇编,最终要生成工程,真正起作用的地方还是在链接,理解了这个点之后,我们接着往下看如何编写一个C语言工程;

二、一个C语言工程实例

点击这里下载例程

​ 这是我第一次使用基站,如果发现不妥请见谅ヽ(*  ̄▽ ̄ *)ノ

​ 好了,回归正题,这个例程呢,是codeblock工程,假如你想用其他的编译器也是一样的,我先使用这个编译器,在接下来的过程中

​ 我写了一个图的程序,这个图的程序呢,主要完成这几件事情,一是图的构建,这其中需要用到相关的结构体,第二个是图的遍历,

​ 这个是我们的工程目录,下面是我们的工程依赖关系

这中间的依赖关系难以用语言描述,我用图形画了出来,配合源码食用;

下面我们来看我在这个工程构建的时候菜的坑:

如何避免重复引用头文件

​ 重复引用头文件会造成怎么样的后果呢,相当于你在一个文件中定义的变量,声明的内容,预编译了两次,那么在编译的时候编译器发现你编译了两次,就会告诉你发生了冲突,重定义了

​ 比如你在a.h中定义了int a,引用了两次,那就是上下文中有两个int a,肯定会报错,不过我的报错没有那么简单,我的报错是结构体引用了两次,中间还用了typedef,报错内容就更复杂了,不过出错的原因很简单,就是重复引用了头文件

​ 那么如何避免重复引用头文件呢?可以使用宏定义ifndef endif

​ 下面我们来介绍如何使用这个东西:

ifndef、endif用法
#ifndef B_H
#define B_H
#include "b.h"
#endif B_H

​ 现在我们来解释一下这个宏定义,ifndef==如果没有定义B_H,那么我们先来定义B_H然后紧跟着引入b头文件,聪明的读者也许发现了,这个B_H是一个标识符,他在我们的程序中起到了标识的作用,如果在别的地方已经定义过B_H了,那么也应该在别的地方已经引入了b.h,所以这时候我们就不需要再引入b.h,而是继续执行endif下面的内容,

​ 也许你会发现,为什么这个工程中引用了多次stdio文件,但是却没有报错?下面我们来介绍防止重复引用头文件的第二种方法:

​ 在被引用的头文件开头使用#pragma once,这样的话该文件就会只预编译一次,简单而好用

为什么说我们要防止重复引用,什么情况下会发生重复引用呢?

我们看这个工程中的这个部分:

​ 我们看这个位置,main.h引用到了dfs头文件,又同时引用到了建立图头文件,而这两个头文件都引用到了studio,在预编译阶段,就会把这些内容同时编译到main.c中,如果没有pragma once,那么stdio头文件就会被编译两次,就发生了头文件重复引用;

​ 吃一堑长一智,大话空话我不说多,我就指出,这个是菱形引入,这样是有可能重复引入头文件的,记住就行了

简单了解C语言如何构建多文件项目的更多相关文章

  1. 【编程学习笔记】如何组织构建多文件 C 语言程序!编程也有~

    优秀 Unix 程序哲学 首先,你要知道这个 C 程序是一个 Unix 命令行工具.这意味着它运行在(或者可被移植到)那些提供 Unix C 运行环境的操作系统中.当贝尔实验室发明 Unix 后,它从 ...

  2. Go语言的构建方法总结

    趁着近期要换工作的空闲时间,看了一下Go语言,与C++相比,Go语言的确在不少地方轻便了不少,例如:增加了内置的字符串类型.多个返回值.支持协程.简单的构建方法等等.使得在生产效率方面有了不少的提高. ...

  3. Python Cookbook(第3版)中文版:15.19 从C语言中读取类文件对象

    15.19 从C语言中读取类文件对象¶ 问题¶ 你要写C扩展来读取来自任何Python类文件对象中的数据(比如普通文件.StringIO对象等). 解决方案¶ 要读取一个类文件对象的数据,你需要重复调 ...

  4. 5分钟APIG实战: 使用Rust语言快速构建API能力开放

    序言:Rust语言简介 参与过C/C++大型项目的同学可能都经历过因为Null Pointer.Memory Leak等问题“被” 加班了不知道多少个晚上.别沮丧,你不是一个人,Mozilla Fir ...

  5. JAVA调用C语言写的SO文件

    JAVA调用C语言写的SO文件 因为工作需要写一份SO文件,作为手机硬件IC读卡和APK交互的桥梁,也就是中间件,看了网上有说到JNI接口技术实现,这里转载了一个实例 // 用JNI实现 // 实例: ...

  6. C语言 HTTP上传文件-利用libcurl库上传文件

    原文  http://justwinit.cn/post/7626/ 通常情况下,一般很少使用C语言来直接上传文件,但是遇到使用C语言编程实现文件上传时,该怎么做呢? 借助开源的libcurl库,我们 ...

  7. 使用nodeJS实现前端项目自动化之项目构建和文件合并

    前面的话 一般地,我们使用构建工具来完成项目的自动化操作.本文主要介绍如何使用nodeJS来实现简单的项目结构构建和文件合并 项目构建 假设,最终实现的项目名称为'test',结构如下图所示 那么,首 ...

  8. 一个简单的C语言程序(详解)

    C Primer Plus之一个简单的C语言程序(详解) #include <stdio.h> int main(void) //一个简单的 C程序 { int num; //定义一个名为 ...

  9. VUE2 第六天学习--- vue单文件项目构建

    阅读目录 VUE2 第六天学习--- vue单文件项目构建 回到顶部 VUE2 第六天学习--- vue单文件项目构建 VUE单文件组件在Vue项目中,然后使用 new Vue({el: '#cont ...

  10. C语言应用操作之文件

    文件是C语言中德中的重点,小编在学习C语言基础知识的时候,大多数的输入输出操作是在屏幕上进行的,现在总算在文件学习上感觉到高大上的样纸.在以前数据量很小时,我们通常将信息从键盘在屏幕上进行输入输出的, ...

随机推荐

  1. 2022春每日一题:Day 17

    今天打CF去了,但是很菜,只做了三题.赛后一分钟做出了第四题,wa了,改了一下下,过了 第一题就是对应的小写字母在大写字母前出现. 第二题直接dfs. 第三题dp,f[i][j]表示以第i个数开始加了 ...

  2. Go语言核心36讲52

    你好,我是郝林. 专栏到这里,就要结束了. 差不多在半年以前(2018年的第二个季度),极客时间的总编辑郭蕾找到我,说想让我写一个关于Go语言的技术专栏. 我那时候还在轻松筹担任大数据负责人,管理着四 ...

  3. Spring Cloud Gateway 使用示例

    Spring Cloud Gateway 使用示例 作者: Grey 原文地址: 博客园:Spring Cloud Gateway 使用示例 CSDN:Spring Cloud Gateway 使用示 ...

  4. 广州2022CCPC补题

    I Infection 知识点: 树上背包 第一次写树上背包的题目,没想到就是在区域赛中 神奇的是树上背包的复杂度,看起来是\(O(n^3)\),但是实际计算只有\(O(n^2)\) 学会树上背包后可 ...

  5. 解决win7连接蓝牙耳机播放设备找不到的问题

    前言 这个问题其实就是蓝牙驱动问题, 而用第三方软件安装驱动,如驱动精灵安装蓝牙驱动,可能会不出现缺失驱动问题,但是一些功能会受到限制(win7系统与其蓝牙驱动不兼容). 解决办法 去 Inter官网 ...

  6. 【Java SE】Day06 类与对象、封装和构造方法

    一.面向对象思想 1.概述:调用对象的行为实现功能,无需一步一步实现(从执行者变成指挥者) 2.类和对象 类是属性和行为的集合,可以看成描述事物的模板 对象是事物的具体体现,是类的一个实例,具备该类的 ...

  7. 【每日一题】【二分mid&贪心】2022年2月8日-NC163 最长上升子序列(一)

    1.描述给定一个长度为 n 的数组 arr,求它的最长严格上升子序列的长度.所谓子序列,指一个数组删掉一些数(也可以不删)之后,形成的新数组.例如 [1,5,3,7,3] 数组,其子序列有:[1,3, ...

  8. 【Spark】Day06-Spark高级课程:性能调优、算子调优、Shuffle调优、JVM调优、数据倾斜、TroubleShooting

    一.Spark性能调优 1.常规性能调优 (1)最优资源配置:Executor数量.Executor内存大小.CPU核心数量&Driver内存 (2)RDD优化:RDD复用.RDD持久化(序列 ...

  9. SVNAdmin2 - 基于web的SVN管理系统

    1. 介绍 SVNAdmin2 是一款通过图形界面管理服务端SVN的web程序. 正常情况下配置SVN仓库的人员权限需要登录到服务器手动修改 authz 和 passwd 两个文件,当仓库结构和人员权 ...

  10. MySQL视图-触发器

    目录 一:视图 1.什么是视图? 2.为什么要用视图? 3.如何使用视图 4.反复拼接的繁琐(引入视图的作用) 5.解决方法 二:视图的应用 1.创建视图的格式: 2.查询视图层 3.查询Navica ...