简单理解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-11-12 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...

  2. VM安装Centos7操作系统

    个人名片: 对人间的热爱与歌颂,可抵岁月冗长 Github‍:念舒_C.ying CSDN主页️:念舒_C.ying 个人博客 :念舒_C.ying 视频教程:https://live.csdn.ne ...

  3. (工具) 性能测试基准软件 lmBench (待补充)

    1. lmBench 介绍 Lmbench是一套简易,可移植的,符合ANSI/C标准为UNIX/POSIX而制定的微型测评工具.一般来说,它衡量两个关键特征:反应时间和带宽.Lmbench旨在使系统开 ...

  4. php7怎么安装memcache扩展

    php7安装memcache扩展 1.下载文件,解压缩 memcache windows php7下载地址: https://github.com/nono303/PHP7-memcache-dll ...

  5. 关于解决linux python3安装gattlib报错

    1. 报错信息 /usr/bin/ld: cannot find -lboost_python36 collect2: error: ld returned 1 exit status error: ...

  6. 关于 risrqnis

    这道题里最有用的( Range Insert Subset Range Query [n?] In Set 破案了 我那五个点是因为维护不知道有什么用的东西炸了 删了就过了 题面 [JRKSJ R4] ...

  7. Android ViewPager2 + Fragment + BottomNavigationView 联动

    Android ViewPager2 + Fragment + BottomNavigationView 联动 本篇主要介绍一下 ViewPager2 + Fragment + BottomNavig ...

  8. Java框架--SSM&Oracle&Maven高级

    〇.内容介绍 一.MyBatis01:框架概述.环境搭建及入门案例.自定义框架 1.介绍 框架:封装细节,是开发中的解决方案 三层架构与SSM的关系 表示层web:SpringMVC框架 业务层ser ...

  9. python各种小知识

    一.三元表达式 1. 简化步骤1:代码简单且只有一行,可以直接在冒号后面编写 三元表达式: 数据值1+ if 条件+else 数据值2条件成立则使用数据值1,条件不成立则使用数据值2: 当结果是二选一 ...

  10. c#5.0(.net 4.5之后)的 Async+await+Task的异步机制的调试笔记

    1.)无返回值的情况(异步也是基于线程). using System; using System.Collections.Generic; using System.Linq; using Syste ...