Linux嵌入式arm视频开发教程笔记3之C语言内存空间的使用

网址:Linux嵌入式ARM开发教程第一阶段_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili https://www.bilibili.com/video/av15875305/?spm_id_from=333.788.videocard.1

  1. 指针: 指针概述
    指针+修饰符 const、voliatile、typedef
    指针+运算符
    多级指针

    数组: 数组空间
    字符空间及地址

    结构体、共用体: 定义、字节对齐
    位域
    内存分布图
    段错误分析

1.指针概述
内存类型资源地址、门牌号的代名词

指针
指针变量:存放指针这个概念的盒子

int a;	*p

C语言编译器对指针这个特殊的概念,有2个疑问?
1.分配一个盒子,盒子要多大?	
	在32bit系统中,指针就4个字节
2.盒子里存放的地址所指向内存的读取方法是什么?

举例:
int *p;
int *p1;
char *p2;	unsigned char *p2;
float b = 1.2;
int a = 0x12345678;	大端小端	0x12  0x34 ...取最低位地址
p  = &b;
p1 = &a;
p2 = &a;	*p2 = 78
printf("the p1 is %u, the p2 is %u\n", sizeof(p1), sizeof(p2));
printf("the p1 is %x\n",*p1);

指针指向内存空间,一定要保证合法性

2.指针+修饰符

const
常量、只读【不能变】
内存属性:
	1、内存操作的大小
	2、内存的变化性,可写可读

char *p;

const char *p;【T】 等价 char const *p;  p可以指向任意,p内容只读
	字符串   "hello world"

char * const p;【T】 等价 char *p const; p指向内容可变,指向地址固定
	硬件资源  LCD

const char * const p;指向固定,指向内容不可变
	ROM内容


volatile
防止优化指向内存地址

typedef
char *p;
什么类型	变量名称
int (*p[10])(int,void(*p)(int));

char *name_t;	name_t是一个指针,指向一个char类型的内容
typedef char *name_t;  name_t是一个指针类型的名称,指向了一个char类型的内存

name_t abc;

3.指针+运算符
+、-
int p = xxx [0x12]
p+1 [0x12+1
(sizeof(*p))]
指针的加法、减法运算,实际上加的是一个单位,单位的大小可以使用sizeof(p[0])

++、--
p++  p--   更新地址


[]
变量名[n]
n:ID  标签
地址内容的标签访问方式

例子:
int a = 0x12345678;
int b = 0x99991199;

int *p1 = &b;
char *p2 = (char *)&b;

printf("the p1+1 is %x,%x,%x\n",*(p1+1),p1[1],*p1+1);
printf("the p2+1 is %x\n",p2[1]);


越界操作
const int a = 0x12345678;
int b = 0x11223344;
//a = 100;

int *p = &b;
p[1] = 0x100;
printf("the a is %x\n",a);	


逻辑操作符
int *p1;
int *p2;

p1>p2
*p1>*p2

1)跟一个特殊值进行比较	0x0:地址的无效值,结束标志
	if( p == 0x0 )
		NULL

2)指针必须是同类型比较才有意义

4.多级指针
int **p;
存放地址的地址空间
把两个或多个不连续的指针变量用指针连在一起,更有顺序逻辑性

#include <stdio.h>
int main(int argc, char **argv)
{
	int i;
	for (i = 0; i < argc; i++){
		printf("the argv[%d] is %s\n",i,argv[i]);
	}
	return 0;
}

测试: ./build hello 123 456


二级指针使用模板
#include <stdio.h>
int main(int argc, char **argv)
{
	int i = 0;
	while(argv[i] != NULL){
		printf("the argv is %s\n",argv[i]);
		i++;
	}
	return 0;
}

5.数组的定义及初始化
内存分配的一种形式

数组的定义及初始化
定义一个空间:
	1、大小
	2、读取方式
数组类型  数组名[m]	m的作用域是在申请的时候
数组名是一个常量符号,一定不要放到=号的左边
例:char buf[100];
buf = "hello world";

int a[100];

越界
a[10]

6.数组空间的初始化
空间的赋值
按照标签逐一处理

int a[10];	[0 - 9]
C语言本身,CPU内部本身一般不支持空间和空间的拷贝
int a[10] = {10,20,30}	====>a[0] = 10; a[1] = 20; a[2] = 30;

数组空间的初始化和变量的初始化本质不同,尤其在嵌入式的裸机开发中,空间的初始化往往需要库函数的辅助

char buf[10] = {'a','b','c'};
buf当成普通内存来看,没有问题
buf当成一个字符串来看,最后加上一个'\0'  0
	字符串的重要属性,结尾一定有个'\0'

char buf[10] = {"abc"};
char buf[10] = "abc";
	buf[2] = 'e';	可以

char *p = "abc";	p指向常量
	p[2] = 'e';	错误


char buf[10] = "abc";
buf = "hello world"	错误
第二次内存初始化,赋值?
应逐一处理
buf[0] = 'h';  buf[1] = 'e' ... buf[n] = 'd'; buf[n+1] = 0;


strcpy,strncpy
strcpy:严重内存泄露函数,只有出现0才停止拷贝,超出内存的怎么办?会把其他的覆盖
strncpy:对拷贝的数量有限制。
一块空间,当成字符空间,提供了一套字符拷贝函数

字符拷贝函数的原则:
内存空间和内存空间的逐一赋值的功能的一个封装体
一旦空间中出现了0这个特殊值,函数就即将结束。

char buf[10] = "abc";
buf = "hello world";
strcpy(buf,"hello world");

字符空间:ASCll码编码来解码的空间

非字符空间:数据采集  0x00-0xff  8bit
	开辟一个存储这些数据盒子
		char buf[10];  -->string
		unsigned char buf[10];  -->data
拷贝三要素:
1、src		2、dest		3、个数

memcpy

int buf[10];
int sensor_buf[100];

memcpy(buf,sensor_buf,10*sizeof(int));

unsigned char buf[10];
unsigned char sensor_buf[100];  // 00 00 00 23 45 78
strncpy(buf,sensor_buf,10);	出现0就停止,拷贝不了后面的数据
memcpy(buf,sensor_buf,10*sizeof(unsigned char));	

7.指针与数组

char * a[100];
sizeof(a) = 100 * 4;

8.多维数组

数组名的保存

定义一个指针,指向int a[10]的首地址
定义一个指针,指向int b[5][6]的首地址

int a[10];
int b[5][6];
int *p1 = a;
int **p2 =b;	错误
int (*p2)[6] = b;

int *p;	int *p[5];
int a;	int a[5];

int *p[5];
int(*p[5]);

int b[2][3][4];
int (*p)[3][4];

9.结构体、共用体定义与字节对齐

字节对齐
char a;
int b;
1+4=5
效率,希望牺牲一点空间换取时间的效率
最终结构体的大小一定是4的倍数
结构体里成员变量的顺序不一致也会影响到他的大小

#include <stdio.h>
struct abc{
	char a;
	short e;
	int  b;
};
struct my{
	char a;
	int b;
	short e;
};
int main()
{
	struct abc buf;
	struct my buf1;
	printf("the buf is %lu:%lu\n",sizeof(buf),sizeof(buf1));
}

10.内存分布图概述
内存的属性:
(1)大小
(2)在哪里

int a;默认方式

编译 --->汇编 ---> 链接

内存分布

*.o		build
内核空间	应用程序不许访问

-----------------------------3G

栈空间		局部变量	RW

运行时的堆空间	malloc

全局的数据空间(初始化的,未初始化的)	static	RW	data bss

只读数据段	“hello world”	字符串常量	R	TEXT

代码段		code			R		TEXT

0x0;

#include <stdio.h>
int main()
{
static int a;
unsigned char *p;
char *p1 = “hello world”;
const int b = 0x12345678;
a = 0x10;

printf("1234the p1 is %s\n", p1);
print("the string address is %p\n", "hello world");
p1[3] = 'a';
printf("the p1 is %s\n", p1);

printf("the a is%p\n", &a);
printf("the is %p\n", main);

p = (unsigned char *)main;

}

  1. 只读空间
    静态空间,整个程序结束时释放内存,生存周期最长

    栈空间
    运行时,函数内部使用的变量,函数一旦返回,就释放,生存周期是函数内

    堆空间
    运行时,可以自由,自我管理分配合释放的空间,生存周期是由程序员来决定

    分配:
    malloc(),一旦成功,返回分配好的地址给我们,只需要接受,对于这个新地址的读法,由程序员灵活把握,输入参数指定分配的大小,单位就是B。

    char *p;
    p = (char *)malloc(100);
    if(p == NULL){
    error
    }

    void fun()
    {
    char *p;
    p = (char *)malloc(100);//申请内存后没有释放,内存泄漏
    return ;
    }

    int a[5]; malloc(5*sizeof(int))

    释放:
    free§;

58个文件/文件夹  41 - 声卡驱动6.mp4 14.7M2017-08-16 22:47  20 - LED设备驱动4.mp4 3.5M2017-08-16 22:47  02 - 开篇的话2.mp4 13.3M2017-08-16 22:47  21 - LED设备驱动5.avi 21.5M2017-08-16 22:47  36 - 声卡驱动1.mp4 15.3M2017-08-16 22:47  47 - LCD驱动6.avi 96.2M2017-08-16 22:47  28 - 电容触摸屏驱动3.avi 59.6M2017-08-16 22:47  29 - 电容触摸屏驱动4.mp4 46.5M2017-08-16 22:47  44 - LCD驱动3.avi 4.3M2017-08-16 22:47  54 - nandflash驱动3.avi 32.7M2017-08-16 22:47  15 - Linux驱动程序开发基础4.avi 66.3M2017-08-16 22:47  18 - LED设备驱动2.mp4 9.7M2017-08-16 22:47  25 - RTC驱动4.mp4 35.9M2017-08-16 22:47  43 - LCD驱动2.mp4 12.9M2017-08-16 22:47  40 - 声卡驱动5.mp4 53.4M2017-08-16 22:47  17 - LED设备驱动1.mp4 19.9M2017-08-16 22:47  53 - nandflash驱动2.mp4 53.9M2017-08-16 22:47  16 - Linux驱动程序开发基础5.mp4 9M2017-08-16 22:47  11 - Linux内核的基本概念5.mp4 37.4M2017-08-16 22:47  35 - 网络设备驱动6.mp4 72.3M2017-08-16 22:47  12 - Linux驱动程序开发基础1.avi 78.6M2017-08-16 22:47  04 - 内核开发初探1.mp4 32.1M2017-08-16 22:47  19 - LED设备驱动3.avi 66.6M2017-08-16 22:47  55 - nandflash驱动4.avi 39.3M2017-08-16 22:47  48 - LCD驱动7.mp4 30.9M2017-08-16 22:47  57 - nandflash驱动6.mp4 3.2M2017-08-16 22:47  09 - Linux内核的基本概念3.avi 10.5M2017-08-16 22:47  14 - Linux驱动程序开发基础3.mp4 14.9M2017-08-16 22:47  06 - 内核开发初探3.mp4 24.4M2017-08-16 22:47  34 - 网络设备驱动5.avi 26.2M2017-08-16 22:47  38 - 声卡驱动3.avi 60.6M2017-08-16 22:47  23 - RTC驱动2.avi 54.8M2017-08-16 22:47  49 - LCD驱动8.mp4 18.3M2017-08-16 22:47  50 - LCD驱动9.avi 25.6M2017-08-16 22:47  24 - RTC驱动3.avi 93.7M2017-08-16 22:47  42 - LCD驱动1.mp4 30.9M2017-08-16 22:47  30 - 网络设备驱动1.mp4 20M2017-08-16 22:47  10 - Linux内核的基本概念4.mp4 33.5M2017-08-16 22:47  26 - 电容触摸屏驱动1.avi 85.4M2017-08-16 22:47  39 - 声卡驱动4.mp4 8.3M2017-08-16 22:47  46 - LCD驱动5.avi 93.9M2017-08-16 22:47  05 - 内核开发初探2.avi 41.9M2017-08-16 22:47  51 - LCD驱动10.mp4 9.2M2017-08-16 22:47  58 - 驱动课程总结提高.mp4 9.5M2017-08-16 22:47  07 - Linux内核的基本概念1.mp4 18.7M2017-08-16 22:47  56 - nandflash驱动5.mp4 31.4M2017-08-16 22:47  45 - LCD驱动4.mp4 31.7M2017-08-16 22:47  31 - 网络设备驱动2.avi 47.2M2017-08-16 22:47  13 - Linux驱动程序开发基础2.mp4 41.4M2017-08-16 22:47  22 - RTC驱动1.mp4 30.7M2017-08-16 22:47  01 - 开篇的话1.mp4 1.3M2017-08-16 22:47  52 - nandflash驱动1.mp4 21.2M2017-08-16 22:47  37 - 声卡驱动2.avi 43.2M2017-08-16 22:47  08 - Linux内核的基本概念2.avi 25.3M2017-08-16 22:47  27 - 电容触摸屏驱动2.mp4 19.3M2017-08-16 22:47  32 - 网络设备驱动3.avi 62.4M2017-08-16 22:47  33 - 网络设备驱动4.mp4 65.1M2017-08-16 22:47  03 - 开篇的话3.mp4 14.3M2017-08-16 22:47
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值