13.物联网之C语言的内存管理,Gcc编译流程与方法

文章详细阐述了内存的四区划分,包括代码区、全局区、栈区和堆区,以及内存的申请与释放。接着,介绍了GCC编译工具的使用流程,包括预处理、编译、汇编和链接四个步骤,并讨论了如何简化编译命令。此外,文章还提到了内存问题,如内存泄漏和内存溢出,以及GCC编译选项如-g用于调试,-O用于优化。最后,讲解了条件编译的概念及其在代码和GCC命令行中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存管理/Gcc编译工具

  1. 内存四区

 代码区: 存放函数体的二进制代码,由操作系统进行管理(cpu执行的机器指令,共享只读)

 全局区(全局静态区): 存放全局变量和静态变量以及常量(包含const)

 栈区: 由编译器自动分配释放,存放函教的参数值,局部变量等

 堆区: 由程序员分配和释放,若程序员不释放程序结束时由操作系统回收

注意:还有一个内核区没有写,用来系统代码,暂时不考虑

  1. 内存分配

2.1申请

#include <stdlib.h>

void *malloc(size_t size);

参数:所需申请空间的大小

返回值:成功 申请空间的首地址

            失败 NULL

2.2释放

void free(void *ptr);

参数:malloc的地址

返回值:无

2.3内存出错

(1)内存泄漏(memory leak):是指申请的内存空间使用完毕之后未回收。

(2)内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用。

  1. Gcc编译工具

使用流程:

  1. gcc -E gcc.c -o gcc.i

-E:预处理 -o:处理后命名为gcc.i

预处理作用:<1>头文件展开<2>宏定义替换

(2)gcc -S gcc.i -o gcc.s

-S:编译处理 -o:处理后命名为gcc.s

编译处理作用:<1>检查语法错误<2>生成汇编文件

(3)gcc -c gcc.s -o gcc.o

-C:汇编处理

汇编处理作用:<1>生成二进制文件/目标文件

(4)gcc gcc.o -o test

链接处理作用:<1>生成可执行文件


出现问题:

        在上述(1)(2)(3)步骤后,不需要第(4)步,直接就可以运行.

解决:-E -S 大写,-c小写,当-C为大写时-C 选项,阻止 GCC 删除源文件和头文件中的注释

所以-c改为小写


辅助记忆:

ESC:编译流程前三个步骤的标记字符

ISO:编译流程进行前三个步骤的文件后缀

最后一步链接不需要标记字符,生成可执行文件.exe(但是不显示.exe)

实现时的简化写法

  1. 分两步写

<1>gcc -c gcc.c -o gcc.o

<2>gcc gcc.o -o test

  1. 一步写

<1>gcc gcc.c -o test

3.1Gcc补充

  1. -c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。

  1. -o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。

<1>o:小写,对应下面大写

  1. -g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。

  1. -O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。

Gcc -O test.c -o test -lphread

<1>O大写:

<2>-lpthread:加入线程库头文件

  1. -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。

  1. -I(大i)  dirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。

例子1:文件在同一个文件目录下

<1>vi main.c

#include “file.h”

Int main(){

fun();

return 0;

}

<2>vi fum.c

#include<stdio.h>

#include”file.h”

void fun(){

printf(“Hello world!”);

}

<3>vi file.h

void fun();

<4>运行

gcc file.c main.c

例子2:文件不在同一目录下

<1>mkdir include

<2>mv file.h include/

<3>gcc main.c file.c -I include(-大i)

注意: <1>-大i

<2>I指定头文件目录

(1).h 写宏定义#define,结构体,申明函数

(2).c 写函数实现

(3)main.c 使用

(7)-L  dirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在链接过程中使用的参数。

例子:

<1>gcc test.c -o test-lpthread

<2>gcc test.c -o test -L/home/linux/ -lpthread

相同:上述两个都是指定库文件

区别:没有-L的是指定系统自带的库文件

有-L的是指定库文件路径,在使用自己写的库文件时使用

4.条件编译

4.1编译条件的概念

一般情况下,C语言源程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译(conditional compile)

应用场景:代码如果包括x86架构和ARM架构,要进行切换,可用条件编译

4.2代码中的条件编译

方法一:根据宏是否定义过来进行条件编译

#define _DEBUG_

Int main(){

#ifdef _DEBUG_ //#ifnedf是没有定义

printf(“Hello”);

#else

printf(“World”);

}

#endif

运行结果:Hello

方法二:根据宏的值是否为真来进行条件编译

#define VALUE 1

#if VALUE

Printf(Hello“”);

#endif

运行结果:Hello

4.3gcc编译时条件编译

命令行中定义或赋值宏来选择编译

gcc main.c -D _DEBUG_

gcc main.c -D VALUE=1

gcc main.c -D VALUE=1 -D _DEBUG_ 两者结合

注意:#ifndef:根据宏是否定义

#if:根据值是否为真

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值