简单理解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. String常用API

    String常用API 1. 获取字符串长度 int length = str.length(); 2. 根据索引,返回字符串中对应的字符 char c = str.chaeAt(length-1); ...

  2. 使用 Spring Cloud LoadBalancer 实现客户端负载均衡

    使用 Spring Cloud LoadBalancer 实现客户端负载均衡 作者:Grey 原文地址: 博客园:使用 Spring Cloud LoadBalancer 实现客户端负载均衡 CSDN ...

  3. cookie中 防止重复存值 (可用于历史记录等)

    function makeCookie($key,$val){ // 查看cookie中是否已经存过键为history_ids if(Cookie::has($key)){ // 已经存过了 $jso ...

  4. i春秋123

    打开是个普普通通的登录窗口,下尝试根据提示12341234进行输入,发现不正确...可能1234是指步骤,然后查看源码 发现了绿色的提示信息,我们就根据提示试试打开user.php 打开是白板网页,源 ...

  5. 3 c++编程-提高篇-模版

    ​ 重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦!  生命就像一朵花,要拼尽全力绽放!死磕自个儿,身心愉悦!  系列文章列表: 1 c+ ...

  6. 一文带你快速入门 Go 语言微服务开发 - Dubbo Go 入门实践总结

    更多详细示例可直接访问 Dubbo 官网 或搜索关注官方微信公众号:Apache Dubbo 1. 安装Go语言环境 建议使用最新版 go 1.17 go version >= go 1.15 ...

  7. 使用Supervisor监控mysql

    Supervisor安装教程参考:https://www.cnblogs.com/brad93/p/16639953.html mysql安装教程参考:https://www.cnblogs.com/ ...

  8. 【SQL】窗口函数:求数据组内累计值和累计百分比

    〇.概述 1.所需资料 窗口函数实现组内百分比.累计值.累计百分比:https://blog.csdn.net/weixin_39751959/article/details/88828922 2.背 ...

  9. 【每日一题】【初始节点初始化,前一个为空】2022年1月7日-NC78 反转链表

    描述给定一个单链表的头结点pHead,长度为n,反转该链表后,返回新链表的表头. 数据范围: n\leq1000n≤1000要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) . 如当 ...

  10. 用最少的代码打造一个Mini版的gRPC框架

    在<用最少的代码模拟gRPC四种消息交换模式>中,我使用很简单的代码模拟了gRPC四种消息交换模式(Unary.Client Streaming.Server Streaming和Dupl ...