嵌入式全栈开发学习笔记---C语言笔试复习大全24

目录

内存管理

内存分配

堆和栈的区别?(面试重点)

申请内存的函数

malloc

realloc 

free

gcc工具链

编译的过程(面试重点)

第一步,预处理:

第二步,编译:

第三步,汇编:

第四步,链接:

常用参数

静态库和动态库的制作(开发重点)

静态库的制作过程

动态库的制作过程


上一篇复习了联合体和枚举,这一篇开始讲解一下内存管理和gcc工具链。

说明:我们学过单片机的一般都是有C语言基础的了,网上关于C语言的资料有很多,大家如果对C语言不熟悉的话可以先去详细学一下,再以这篇博文作为复习资料学习。

这篇博文的目的是复习C语言,我们会陆续以30多个编程题作为复习要点,这30多个编程题基本涵盖了C语言所有的内容了,只要你掌握了这30多个编程题,那么你的C语言基本就没什么问题了。

注意:由于本专栏是嵌入式全栈开发专栏,为了我们能熟悉以后实际工作中的开发环境,我们写C语言全部在Linux中的vim编辑器中写,这么做事为了我们能够熟练掌握Linux系统的常用命令以及Linux上的vim编辑器的常用工作命令,以达到对口训练的目的!

vim编辑器的一些工作命令在上一篇博文中已经详细介绍过了,如果不了解可以先去看看。

我们正式开始:

内存管理

C语言不能直接操作物理内存,程序中使用的内存都是虚拟内存(一个进程再启动的时候,系统都会给它分配4个G的虚拟内存,一般情况下是按1:3来分配的,1个G给系统内核来使用,3个G给应用层来使用)。

内存分配

3个G的内存又分为:

注:

以上表格有的时候会分为5段,就是把数据段分为数据段和BSS段,即已初始化数据段

和未初始化数据段。

有的时候将以上表格分为3段,就是将堆和栈分到一起,称为堆栈。

静态数据区也在数据段,比如static修饰的变量;

代码段存放的是编译好的二进制文件;

例如:

//全局变量
int num; //未初始化数据段,BSS段
char ch=’x’; //已初始化数据段int main()
{char*s=”helloworld”;// s存放在栈空间,”helloworld”属于只读数据段,不能被修改s[0]=’x’;//这样写是不行的,”helloworld”属于只读数据段,不能被修改static int a=0;//静态数据区char *p=(char*)malloc(sizeof(char)*128);//p栈空间,申请的128个字节属于堆空间char p1[ ]=”helloworld”; //p1是局部变量在栈空间,”helloworld”放在p1里面的,所以”helloworld”就是在栈空间char *p2=”helloworld”; //p2属于栈空间,占8个字节,它指向了只读数据区的”helloworld”return 0;
}

堆和栈的区别?(面试重点)

  1. 堆空间是用户管理的,用户申请,用户释放;而栈空间是系统管理的,当用户定义一个变量的时候,系统会自动为它开辟一个空间,当一段程序运行完时候,系统会自动释放掉这个空间。
  2. 堆空间更大,栈空间更小,如果我们要申请连续的大内存,比如说10万个整数,我们可以去堆空间申请。
  3. 堆空间使用效率低(因为空间大,内存记在一个链表里面,申请内存时,它需要去查一下链表,查一下哪边可以使用),栈空间使用效率高(一直往前申请就可以了)。
  4. 堆空间函数结束不会释放(需要用户手动释放),栈空间函数结束自动释放。

申请内存的函数

malloc

函数原型:

void *malloc(size_t size)

realloc 

函数原型:

void *realloc(void *ptr, size_t size)

如果你用malloc申请128个字节不够用了,可以通过realloc从128个字节后面即第129个字节开始再申请一些空间,但是前提是后面够用。

如果第128个字节后面不够用了,它会在其他的地址给你申请一个空间,将前面128个字节的内容拷贝进去,然后再在后面给你申请一块空间,返回一个新地址给你使用。

所以realloc相当于是拓展内存的。

free

动态申请的内存需要手动释放,如果不释放,会造成内存泄漏。释放后的指针应该置为空指针,否则会变成野指针。

gcc工具链

这一节我们来详细讲一节关于编译的事情。

一般我们在Linux终端想要编译我们写好的.c文件的话,直接就是输入“gcc 文件名.c -o 文件名”就行,但其实这一个过程是分为4个步骤进行的:

编译的过程(面试重点)

第一步,预处理:

处理所有以#开头的代码,包括头文件、宏定义、条件编译

比如:gcc -E hello.c -o hello.i

注:.i就是预处理后的文件。

头文件预处理过程就是将头文件直接展开。意思就是它会到操作系统里面把stdio.h这文件给找出来,然后将这个文件的内容复制一份粘贴出来,这就是将头文件展开的操作。

头文件的”<>”尖括号就是表示到系统指定的目录下面去找。

这是头文件的预处理过程。

宏定义比如#define PRICE 10    int sum=PRICE*100;预处理的话直接就是将PRICE替换成int sum=10*100

条件编译的预处理过程就是直接把#if 0....#endif框选的代码丢掉。

如果你写了一段代码后不需要它了,就可以这样:

#if 0

Void f1()

{

Printf(“helloworld\n”);

}

#endif

这种操作类似于/*  */注释掉代码。

第二步,编译:

语法检查以及将C语言变成汇编语言

比如:gcc -S hello.i -o hello.s

注:编译后的文件是.s文件,也就是汇编文件。

第三步,汇编:

将汇编语言变成二进制文件

比如:gcc -c hello.s -o hello.o

注:.o文件就是二进制文件。

以ELF开头,就是二进制文件:

我们可以用file来看一下

第四步,链接:

链接代码需要用到的其他文件(库文件等)

比如:gcc hello.o -o hello

上一步得到的.o文件还是不能够直接执行,是因为它还差一步。比如我们刚刚写的这个代码用到了printf,当程序从main()函数开始执行到printf这里时,它不知道printf是什么东西,我们还差一步链接的操作,即把“printf这个代码在哪”这个信息链接到原文件里面去。

链接有两种,一个是静态链接,一个是动态链接(我们直接写的“gcc 文件名.c -o 文件名”就是一种动态的链接)。

动态链接就是将“printf这个代码在哪”这个信息链接到原文件里面去,等到运行的时候它会根据我们提示的位置信息就找到printf()这个函数,这样才能执行。如果libc文件丢了则不能执行了。

比如gcc hello.o -o hello-动态

静态链接生成的二进制文件比动态链接的文件大。因为静态链接时是直接将libc中的printf()函数的实现放到生成的二进制文件中。但是,这种方式在libc文件丢失的情况下还是可以执行。

比如gcc hello.o -o hello-静态 -static

常用参数

-c:只是编译不链接,生成目标文件“.o”

-S:只是编译不汇编,生成汇编代码

-E:只进行预编译,不做其他处理

-g:在可执行程序中包含标准调试信息,用gdb调试程序的时候用到。

-o file:把输出文件输出到file里

-V:打印出编译器内部编译各过程的命令行信息和编译器的版本

-I dir:大写的i,在头文件的搜索路径列表中添加dir目录,如果我们写的头文件和.c文件不是在同一个文件中,编译的时候可以将头文件放在-I后面。

-L dir:在库文件的搜索路径列表中添加dir目录,链接静态库和动态库的时候用到。

-static: 链接静态库

-l library :连接名为library的库文件

静态库和动态库的制作(开发重点)

静态编译用到静态库,动态编译用到动态库;

静态库的制作过程

什么是静态库?怎样制作静态库?

1、写一个hello.c文件,里面调用了f1()和f2()两个函数,然后f1()和f2()的实现分别写在单独的文件f1.c和f2.c中。

hello.c

f1.c

f2.c

 

2、接下来首先第一步是将f1.c和f2.c两个原文件转换成二进制文件。输入”gcc -c f1.c f2.c”这样就会自动生成两个.o文件。

 

3、然后我们用“ar -crv lib(静态库的名字随便取).a f1.o f2.o”,注意一定是以lib开头,加上静态库的名字,.a是静态库的后缀,比如“ar -crv libx.a f1.o f2.o”x就是静态库的名字。最终生成的libx.a文件就是静态库。

 

4、当我们拿到这个静态库的时候,要执行hello.c文件就要结合这个静态库才行,比如“gcc hello.c -o hello -static -L . -l x”。

注:“.”表示在当前目录下面。-static是静态链接,-L 后面接库文件的路径,-l后面是库文件的名字。

这样它就生成了hello的二进制文件

 

5、接下来我们改一下hello.c文件,在main()函数的上方声明一下f1和f2这两个函数。

声明之后我们就可以正常编译hello.c文件了。

动态库的制作过程

什么是动态库?怎样制作动态库?

1、同上,写好f1.c和f2.c和hello.c文件之后,输入“gcc -fPIC -shared -o lib库的名字.so f1.c f2.c”,比如gcc -fPIC -shared -o libxx.so f1.c f2.c,最终生成的libxx.so就是动态库。

 

2、我们编译hello.c文件之前先链接动态库,“gcc hello.c -o hello -L . -l xx”。

 

3、链接好之后用ldd 加上”gcc hello.c -o hello -L . -l xx”这一步操作后生成的二进制文件名来看看它会默认去取哪里找,比如我们看到它会去/lib这个目录下面去查找,我们将libxx.so动态库拷贝到/lib目录下。

注:不同的操作系统可能会去不同的目录下去找,ldd 加上”gcc hello.c -o hello -L . -l xx”这一步操作后生成的二进制文件名可以查找二进制文件所用到的库在哪。

拷贝进去/lib中

这个时候我们再执行hello就成功了

以上就是这篇内容,如想了解更多,欢迎订阅本专栏!

如有问题可评论区或者私信留言,如果想要进交流群请私信!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/15691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决LabVIEW通过OPC Server读取PLC地址时的错误180121602

在使用LabVIEW通过OPC Server读取PLC地址时&#xff0c;若遇到错误代码180121602&#xff0c;建议检查网络连接、OPC Server和PLC配置、用户权限及LabVIEW设置。确保网络畅通&#xff0c;正确配置OPC变量&#xff0c;取消缓冲设置以实时读取数据&#xff0c;并使用诊断工具验证…

2 使用香橙派AIpro报错 No module named ‘acllite utils‘

当使用jupyter运行香橙派的notebooks下面的案例的时候启动使用jupyter lab 然后自动跳转到jupyter页面。如下图: 这是自动跳转过来的。然后运行下面的包的导入后报错: 报错为No module named ‘acllite utils’,那么我们打开notebooks文件夹下面的start_notebooks.sh文件:…

【C++练级之路】【Lv.21】C++11——列表初始化和声明

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、列表初始化1.1 内置类型1.2 结构体或类1.3 容器 二、声明2.1 auto2.2 decltype2.3 nullptr 三、STL的…

从“反超”到“引领”,中国卫浴品牌凭何遥遥领先?

作者 | 曾响铃 文 | 响铃说 前不久&#xff0c;第28届中国国际厨房、卫浴设施展览会(以下简称“中国国际厨卫展”)在上海如期举行&#xff0c;就结果来说真的让人大开眼界。 冲水声比蚊子声更小的马桶、能化身无感交互平台的魔镜柜、可以语音交互的淋浴器&#xff0c;这些“…

Keli5烧写STM32程序时出现ST-LINK USB communication error错误(USB 通信错误)

1错误原图 2错误原因 前提驱动安装正确 原因1 usb接触不良&#xff08;极少出现&#xff09; 解决方法 更换USB线 还不行连下载器一起更换 原因2&#xff08;出现概率比较大&#xff09; 下载器的固件出现问题或下载器固件版本与Keli5的版本不匹配 解决方法 在Keli5的…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 5月26日,星期日

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年5月26日 星期日 农历四月十九 1、 医保局&#xff1a;支持将符合条件的村卫生室纳入医保定点&#xff0c;方便农村居民就医。 2、 网传养老金储备严重不足&#xff1f;央视辟谣&#xff1a;这笔钱二十多年来从未动用过&a…

搭建企业级AI应用的流程

搭建企业级AI应用的流程是一个复杂且系统化的工程&#xff0c;它需要从多个维度出发&#xff0c;确保最终的应用既符合企业的业务需求&#xff0c;也具备高效、稳定和可扩展的特性。以下是详细的步骤&#xff1a; 初步接触与需求分析是整个项目的基础。在这一阶段&#xff0c;我…

【C++题解】1698. 请输出带有特殊尾数的数

问题&#xff1a;1698. 请输出带有特殊尾数的数 类型&#xff1a; 题目描述&#xff1a; 请输出1∼n 中所有个位为 1、3、5、7中任意一个数的整数&#xff0c;每行 1 个。( n<1000 ) 比如&#xff0c;假设从键盘读入 20&#xff0c;输出结果如下&#xff1a; 1 3 5 7 11 1…

LLMs之PEFT之Llama-2:《LoRA Learns Less and Forgets LessLoRA学得更少但遗忘得也更少》翻译与解读

LLMs之PEFT之Llama-2&#xff1a;《LoRA Learns Less and Forgets LessLoRA学得更少但遗忘得也更少》翻译与解读 导读&#xff1a;该论文比较了LoRA与完全微调在代码与数学两个领域的表现。 背景问题&#xff1a;微调大规模语言模型需要非常大的GPU内存。LoRA这一参数高效微调方…

OpenStack平台Keystone组件的使用

1. 规划节点 安装基础服务的服务器规划 IP地址 主机名 节点 192.168.100.10 controller Openstack控制节点 2. 基础准备 使用机电云共享的单节点的openstack系统&#xff0c;自行修改虚拟网络编辑器、网络适配器&#xff0c;系统用户名&#xff1a;root&#xff0c;密…

【Basic】Upload-Labs-Linux

文章目录 前言Pass-01Pass-02Pass-03Pass-04Pass-05Pass-06Pass-07Pass-08Pass-09Pass-10Pass-11Pass-12Pass-13Pass-14Pass-15Pass-16解题感悟 前言 美好的一天从刷题开始 Pass-01 我淦20道题&#xff1f;&#xff1f;&#xff1f;一道一道来吧 先看第一道题 先在home里搞一…

原生标签WebComponent

文章目录 介绍一、web Component二、怎么使用三、在Vue中使用使用场景 前端必备工具推荐网站(免费图床、API和ChatAI等实用工具): http://luckycola.com.cn/ 介绍 平常浏览各个网站过程中&#xff0c;经常遇到的一种现象&#xff1a;页面广告。 这种广告按照来源可分为两种&…

蜜罐技术是一种什么防御技术?实现原理是什么?

前言&#xff1a;蜜罐技术的出现改变了这种被动态势&#xff0c;它通过吸引、诱骗攻击者&#xff0c;研究学习攻击者的攻击目的和攻击手段&#xff0c;从而延缓乃至阻止攻击破坏行为的发生&#xff0c;有效保护真实服务资源。 自网络诞生以来&#xff0c;攻击威胁事件层出不穷…

类和对象【六】友元和内部类

文章目录 友元友元的作用友元的缺点友元函数语法&#xff1a;特点&#xff1a; 友元类语法&#xff1a;特点&#xff1a; 内部类概念特点 友元 友元的作用 友元提供了一种打破封装的方式&#xff0c;有时提供了便利。 友元的主要作用就是打破封装 即可以让一个类的友元函数…

爬虫100个Python例子优化

今天看到一个Python 100例的在线资源,感觉每个都需要去点,太费时间了,于是,使用Python将数据爬取下来,方便查看。实际效果如下: 。。。。。。 用了13分钟,当然,这是优化后的效果,如果没有优化,需要的时间更长。 爬取url如下: https://www.runoob.com/python/pytho…

uniapp+vue3+ts开发小程序或者app架构时候的UI框架选型

使用vue3tsviteuniapp开发小程序或者跨平台app的趋势越来越高&#xff0c;有一个顺手的UI的框架还是非常重要的&#xff0c;官方维护的 uni-ui&#xff0c;支持全端&#xff0c;而且有类型提示&#xff0c;目前已经内置到 GitHub - Sjj1024/uniapp-vue3: 使用uniapp和vue3 ts …

搭建CMS系统

搭建CMS系统 1 介绍 内容管理系统&#xff08;Content Management System&#xff0c;CMS&#xff09;是一种用于管理、发布和修改网站内容的系统。开源的CMS系统有WordPress、帝国CMS等&#xff0c;国产的Halo很不错。 WordPress参考地址 # 官网 https://wordpress.org/# …

Python脚本必加代码:99%的程序员都忽视了这个细节!

文章目录 一、初识 if __name__ __main__二、__name__ 和 __main__ 是什么&#xff1f;三、实战讲解四、实际应用场景测试代码提高代码可重用性避免不必要的执行 五、深入理解和更多用法使用 argparse 解析命令行参数使用 unittest 进行单元测试使用 multiprocessing 创建子进…

嵌入式全栈开发学习笔记---C语言笔试复习大全22

目录 结构体 结构体的声明 定义结构体变量 访问结构体成员进行初始化 通过结构体变量名访问结构体成员 结构体指针 结构体指针的定义 通过结构体指针访问结构体成员 结构体数组 结构体数组的定义 遍历结构体数组 结构体的长度&#xff08;笔试重点&#xff09; 上一…

哈希双指针

文章目录 一、哈希1.1两数之和1.2字母异位词分组1.3最长子序列 二、双指针2.1[移动零](https://leetcode.cn/problems/move-zeroes/description/?envTypestudy-plan-v2&envIdtop-100-liked)2.2[盛最多水的容器](https://leetcode.cn/problems/container-with-most-water/d…