C语言内存话题

嵌入式软件工程师学习路线 朱有鹏老师语录:学习如走夜路,人多心里不慌。

1、嵌入式基础预科

2、ARM裸机全集

3、C语言高级专题

4、Uboot和系统移植

5、Linux应用编程和网络编程

6、Linux驱动开发实战

----------------------------------------------------

内存这个大话题

C语言:C语言中编译器帮我们管理直接内存地址。通过编译器提供的变量名等来访问内存。

大块内存通过API(malloc free)来申请释放内存。

JAVA/C#:不直接操作内存,通过虚拟机操作内存,管理,释放内存。虚拟机回收内存需要付出代价。

C语言就如同,在家吃饭,自己洗碗。

java/C#等高级语言如同,在外面吃饭,吃完就走了,但是要付出一定代价。

C语言中一个变量实际就对应内存的一个单元。

内存单元的大小单位

-----------------

位bit    1bit

字节byte  8bit

半字  一般16bit

字   一般32bit

------------------

CPU只认识内存地址,地址和空间是内存单元的两个方面.

内存编址是以字节为单位.

------------------------------------------------------------------------------------------

数据类型

C语言基本数据类型 char short int long float double

int 整型(整数类型,这个整就体现在它和CPU本身的数据位宽一样)

32bit的CPU == 整型就是32bit == int 32bit

数据类型是用来定义变量,而这些变量需要存储、运算在内存中。所以数据类型必须和内存相匹配才能获得最好的性能,否则可能不工作或者效率低下。

在32位系统中定义变量最好用int,因为这样效率高。原因就在于32位系统.本身配合内存等也是32bit,这样的硬件配置天生适合定义32bit的int类型变量,效率最好。也能定义8bit的char或16bit的short,实际访问效率不高.

在32bit环境下,定义bool类型变量,(实际只需要1个bit),都是用int来实现bool

编译器帮分配了int来存储bool,实际浪费了31bit的内存,但是效率高。

问题:实际编程时要以省内存为大还是要以运行效率为重?看具体情况

现在写程序重要是效率和用户体验关键。(内存变得便宜,不在乎)

内存对齐

定义int 4个字节

0 1 2 3   对齐访问

1 2 3 4 / 2 3 4 5 / 3 4 5 6 非对齐访问

内存的对齐访问不是逻辑问题,硬件的问题。32位的内存0 1 2 3 逻辑就有相关性,硬件上合适,效率高。

对齐访问很配合硬件,效率很高;

非对齐访问因为和硬件本身不搭配,效率不高

因为兼容性的问题,一般硬件也都提供非对齐访问,但是效率低

----------------------------------------------------------------------------

C语言对内存地址的封装(用变量名来访问内存、数据类型的含义、函数名的含义)

数组 连续的空间

首地址

首元素

首元素的首地址

int a;//编译器申请一个int类型的内存格子(长度4字节,地址确定,符号a与这个格子绑定)

a = 5;// 5 丢到 符号a绑定的格子里去

a += 4;//9

C语言中数据本类型的本质含义是:表示一个内存格子的长度和解析方法.

数据类型决定长度的含义:

我们一个内存地址,本来这个地址只代表1个字节的长度,给他一个类型,让他有了长度.这样这个代表内存地址的数字就能从这个数字开头的连续n个字节的内存格子。

数据类型决定解析方法的含义:有一个内存地址,给这个内存地址不同的类型来指定这个内存单元格子中二进制数的解析方法.

(int)0x30000000  4个字节连起来共同存储是一个int

(int *)0; //0数据的地址解析方式-int*类型(0存一个指针,指向int)

(float *)0;

(short)0;

(char)0;//0 地址存一个char变量

函数就是一段代码的封装,函数名的实质就是这一段代码的首地址。

函数名的本质就是一个内存地址.

用指针来间接访问内存

类型只是对后面数字或者符号(内存地址)所表征的内存的一种长度规定和解析方法

数组管理内存和变量,只是符号的解析方法不同

int a; //编译器分配4字节长度给a,并且把首地址和符号a绑定.

int b[10];//编译器分配40个字节长度给b,首元素的首地址和b绑定.

-------------------------------------------------------------------------------

内存管理之结构体

数据结构就是研究数据如何组织(在内存中排布)如何加工

数组下标访问,编译器帮计算内存地址

a[0]   a[2] = a[0] + 2*4

数组-优点 :数组比较简单,访问用下标,随机访问

缺点 : 元素类型必须相同,大小必须定义时给出,一旦确定不能再改。

结构体发明解决数组的第一个缺陷:数组中所有元素类型必须相同

结构体内嵌指针实现面向对象。

C语言是面向过程的,但是C语言写出linux系统是面向对象的。

用C++ java等面向对象的语言来实现面向对象简单一些,因为语言本身帮我们做了很多事情;但是用C来实现面向对象很麻烦。

struct a

{

int age;

void (*func)(void);//函数指针,指向void func(void)这类的函数

};

使用这样的结构体就可以实现面向对象。这样包含了函数指针的结构体就类似于面向对象的class。结构体中的变量类似于class的成员变量。函数指针类似于class的成员方法。

-------------------------------------------------------------------------------------------

栈是一种数据结构,C语言使用栈保存局部变量,管理内存)

栈管理内存特点(小内存、自动化)

C语言中的局部变量用栈来实现的。

定义一个局部变量时,编译器会在栈中分配一段空间,栈指针的移动和内存分配时自动(栈自己完成)

函数退出,局部变量灭亡,出栈。

C语言中,定义局部变量,如果未初始化,值随机,栈内存反复使用(脏的,上次用完没清零)

显示初始化

int a = 15;//局部变量定义时,初始化

C语言编译器自动把这行转成

int a;  //定义

a = 15;//赋值

栈的约束(预定栈大小不灵活,怕溢出)

栈是有大小的。栈内存大小不好设置。太小怕溢出,太大怕浪费内存。

C语言定义局部变量不能太多,太大,递归问题要递归收敛一点。

-------------------------------------------------------------------------------------------

堆    堆栈(栈)

heap  内存管理(随时申请、释放、大小块随意)

堆内存,向使用者(用户进程)提供API(malloc和free)

需要内存容量比较大,需要反复使用及释放(数据结构的实现-链表)

堆管理内存特点

1 容量不限

2 申请、释放 手工进行malloc free,未释放-内存丢失,内存泄漏

堆管理器中内存仍属于这个进程,但进程自己又一位这段内存不用了,再用的时候又会去申请的内存这叫吃内存

C/C++ 内存泄漏最严重的程序bug

Java / C# 内存管理,只需要使用,不需要释放

man 3 free  man手册

void free(void *ptr);

堆内存申请

realloc、calloc、malloc

void *malloc(size_t size);

void *calloc(size_t nmemb,size_t size);//  多少 单位

void *realloc(void *ptr,size_t size);//改变原来申请空间的大小

数组定义大小无法更改

java中障眼法-更改数组大小

1、先重新创建一个新数组的大小

2、原数组的元素复制进新的数组

3、释放原数组

4、返回新数组给用户

堆内存申请给大小,一旦申请完成大小不变,如果要变通过realloc

申请10个int元素内存

malloc(40)   malloc(10*sizeof(int));

calloc(10,4) calloc(10,sizeof(int));

------------------------------------------------------------------------------------------

时间: 2024-10-06 10:08:54

C语言内存话题的相关文章

c语言内存四区模型

c语言内存四区模型:代码区,全局区(常量区),栈区,堆区 在全局区(常量区),两个字符串完全一样c++编译器只会定义一份 char * getBuf() { char buf[20]; strcpy(buf, "abcde"); return buf; } abcdX?  有乱码! 确实把内存地址返回了,但不能用 被调函数调用完毕,在临时区分配的内存统统消失 char *buf= (char *)malloc(sizeof(char)*20); 手动malloc申请一份内存,由程序员手

C语言内存调试技巧—C语言最大难点揭秘

本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内.内存错误是 C 和 C++ 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终没有彻底解决,它们可能严重影响应用程序,并且很少有开发团队对其制定明确的管理计划.但好消息是,它们并不怎么神秘.引言C 和 C++ 程序中的内存错误非常有害:它们很常见,并且可能导致严重的后果.来自计算机应急响应小组(请参见参考资料)和供应商的许多最严重的安全公告都是由简单的内存错误造成的.自从 70 年代末期以来,C 程序员就一直讨论此

C语言内存使用的常见问题及解决之道

一  前言 本文所讨论的“内存”主要指(静态)数据区.堆区和栈区空间(详细的布局和描述参考<Linux虚拟地址空间布局>一文).数据区内存在程序编译时分配,该内存的生存期为程序的整个运行期间,如全局变量和static关键字所声明的静态变量.函数执行时在栈上开辟局部自动变量的储存空间,执行结束时自动释放栈区内存.堆区内存亦称动态内存,由程序在运行时调用malloc/calloc/realloc等库函数申请,并由使用者显式地调用free库函数释放.堆内存比栈内存分配容量更大,生存期由使用者决定,故

c语言内存模型

文章一.C语言的内存分配模型 1.程序代码区:存放函数体的二进制代码. 2.全局区数据区:全局数据区划分为三个区域.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域.常量数据存放在另一个区域里.这些数据在程序结束后由系统释放.我们所说的BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称. 3.栈区:由编译器自动

C语言内存模型 (C memory layout)

 一. 内存模型                                                                         1. .text 代码区(code section).由编译器链接器生成的可执行指令,程序执行时由加载器(loader)从可执行文件拷贝到内存中.为了安全考虑,防止别的区域更改代码区数据(即可执行指令),代码区具有只读属性.另一个方面,代码区通常具有可共享性(sharable),即在内存中只有一份代码区,如编译器,假如同时有多个编译任务

C语言内存分布

C语言内存分布 典型的C语言程序内存表示分区共有5个部分: 正文段 Text segment 已初始化数据段(数据段)Initialized data segment 未初始化数据段(bss)Uninitialized data segment 堆 Stack 栈 Heap 具体分布图 各个分区的作用 正文段 CPU执行的机器指令部分 通常可共享 常常是只读的 已初始化数据段(数据段) 包含程序中需明确赋初始值的变量 保存已经初始化的全局变量 未初始化数据段(BSS) 在程序开始执行之前,内核将

C语言内存分析

一.进制 概念:进制是一种计数方式,是数值的表现形式 4种主要的进制: ①. 十进制:0~9 ②. 二进制:0和1 ③. 八进制:0~7 ④. 十六进制:0~9+a b c d e f C语言在默认的情况下为十进制. int num=1010; // 十进制 int num=0b1100; // 二进制,以0b或者是0B开头 int num=014; // 八进制,以0开头 int num=0x4; // 十六进制,以0x开头 占位符: %d和%i :十进制整数的形式输出一个值 %o :以不带符

Go语言内存分配机制

前言: 本文是学习<<go语言程序设计>> -- 清华大学出版社(王鹏 编著) 的2014年1月第一版 做的一些笔记 , 如有侵权, 请告知笔者, 将在24小时内删除, 转载请注明出处! Go语言有两种内存分配机制 , 分别是内置函数 new() 和make(). - new() - 定义: func new(Type) * Type - 返回值是一个内存块指针 - new() 是一个内置函数, 不同于其他语言中的new操作符, 它只将内存清零, 而不是初始化内存. - make(

浅谈C语言内存管理、内存泄露、堆栈

1.内存分配区间: 对于一个C语言程序而言,内存空间主要由五个部分组成:代码段(.text).数据段(.data).静态区(.BSS).堆和栈组成. BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量和静态变量 (这里注意一个问题:一般的书上都会说全局变量和静态变量是会自动初始化的,那么哪来的未初始化的变量呢?变量的初始化可以分为显示初始化和隐式初始化,全局变量和静态变量如果程序员自己不初始化的话的确也会被初始化,那就是不管什么类型都初始化为0,这种没有显示初始