嵌入式LinuxC--指针与数组

一、指针
1.指针是什么?
指针是一种变量,用来保存数据(即地址)
保存的数据固定长度(也就是地址的长度固定,由操作系统决定。
占用字节4/8个

2.指针运算

  • :取值运算符
    *ptr :取指针ptr变量对应对应内存空间的地址所对应的内存空间的值
    取ptr变量指向的内存的值
    在这里插入图片描述
    对应内存空间 VS指向的内存空间
    对应内存空间:即储存变量ptr的的地方
    指向的内存空间:变量ptr保存的是地址,这个地址指向的空间就是指向的内存空间

多级指针的作用
保存上一级指针变量的地址
在这里插入图片描述
指针数值运算
ptr++:指针向后走一个字节
ptr + 1:指针向后走一个步长
指针的步长:由指针的类型决定
指针赋值运算:
必须是步长相同的指针,才能进行赋值运算

void :空指针,即万能指针
1.可以接受任意类型指针的赋值
2.不能做取值操作
3.步长是一个字节
4.赋值是,void
必须进行强制类型转换,转换到确定的类型 // int *ptr1 = (int *)void *ptr2;

两个指针之间,只能相减(计算两个指针之间相差的位数),不能相加

3.野指针
由于编译器优化,所有的未指明地址的指针会被初始化为0,即将指针置为NULL。零地址是不能操作、不能赋值的,一般编译时会报段错误,而且这种错误不容易检查。
所以,我们在定义指针时,对于没有初始地址的指针,要给它赋值为NULL,提醒自己该指针是不能操作、不能赋值的,避免出现错误。
int main()
{
char *ptr; <------ 野指针,会随机指向一个地址,导致内存泄漏
}

什么是野指针?
随机指向一块内存的指针;释放空间后的指针;

野指针的影响?
会导致内存泄漏

如何避免野指针?
要养成良好的编码习惯:
1.指针没有指向时,要置空;char* ptr = NULL;
2.指针被释放后,要置空。

给指针分配空间、并释放
char* ptr = (char *)malloc (sizeof(char)*100);
free(ptr);
ptr = NULL;

指针被置空的原因?
提示自己该指针不能操作、不能赋值,防止出现错误。
在这里插入图片描述
4.malloc 分配内存空间 单位:字符
mallloc的返回值是 void *
形参、传参:
char *ptr = (char *)malloc(sizeof(char) * 100)

malloc的返回值要进行强制类型转换
检查mallloc是否分配成功
char *ptr = (char *)malloc(sizeof(char) * 100)
if(NULL == ptr)
{
printf(“malloc is error\n”);
exit(1);
}

对分配的空间进行初始化
meset(ptr, 0, sizeof(char) * 100)
ezero(ptr, sizeof(char) * 100)

使用时不要越界访问

------>free的注意事项
释放之后要将指针置空
free(ptr);
------>free是如何知道要释放多大的内存?
malbc
需要额外40个字节
来保存malbc分配的100个字节的信息、属性


存储100个字节的信息



malbc的缺点:大开销操作(无论存储多少个字节的信息,都需要40个字节来保存这些字节的信息、属性)
------->解决方法:内存池
------->malbc是如何实现的?malbc是如何获取内存的?

二、数组
1.一维数组 //int a[100]
a 数组名:是一个指针常量(不能用来自加自减),保存数组首元素的地址
&a &数组名:数组的地址
int num = 5;
num 0x1003
0x1002
0x1001
0x1000
一个变量的地址由首个字节的地址决定&num = 0x1000

二、数组
1.一维数组 //int a[100]
a 数组名:是一个指针常量(不能用来自加自减),保存数组首元素的地址
&a &数组名:数组的地址

int num = 5;
num 0x1003
0x1002
0x1001
0x1000
一个变量的地址由首个字节的地址决定&num = 0x1000

int a[4] = {0};
a[3] 0x100c
a[2] 0x1008
a[1] 0x1004
a[0] 0x1000
&a—>0x1000 a---->0x1000

2.数组指针
实质上是一个指针,用来保存一个数组的地址
int (*pa)[3]
pa = &a; *pa = a;
—>对一组数组的地址取值,等于首元素的地址

3.二维数组
二位数组的输入输出
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
int aa[2][2] = {0};

for(i = 0;i < 2; i++)
{
    for(j = 0;j < 2; j++)
    {
        scanf("%d", &a[i][j]);
        //printf("%d",a[i][j]);
    }
}

retuen 0;

}

aa 二维数组名:是一个指针常量,保存的是二维数组中首个以为数组的地址
&aa &二维数组名:取二维数组的地址

4.二维数组指针
int (*paa)[3];
paa = &aa;

5.三维数组
int aaa[2][2][2] = {{1, 2, 3, 4},{5, 6, 7, 8} //有2个二维数组
aaa[0][0][0] = 1; aaa[0][1][0] = 3;
aaa[1][0][0] = 5; aaa[1][1][0] = 7;

aaa 三维数组名:是一个指针常量,保存的是三维数组中首个二维数组的地址
*aaa :三维数组中首个二维数组中的首个一维数组的地址
**aaa:三维数组中首个二维数组中的首个一维数组的首元素的地址。

6.三维数组指针
int (*paaa)[3];
paaa = &aaa;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
7指针数组:实质上是一个数组,数组里面放的是指针
int *ptr[3];
指针数组里的元素一开始都是野指针,要对其进行分配空间
在这里插入图片描述
-------->指针数组主要用来给主函数传参:
argc:统计传入主函数参数的个数(其中包括编译命令)
*argv[]:传入的参数保存在argv中

使用:
int main(argc,char *argv[]//或者:char **argv)
入口输入检查(检查输入的变量是否符合要求)
if(argc != 3)
{
exit(1);
}
在这里插入图片描述
8.函数指针:保存函数的入口地址(即函数的地址)
int (*p_func)(int, int);
函数名与&函数名:意义相同,表示一个指针,保存的是函数的口地址
使用:

int (p_func)(int, int);
p_func = add;
函数指针作为形参指向的函数,称为回调函数
在这里插入图片描述
9.函数指针数组
是一个数组,数组内的每一个元素都是函数指针
int (
p_arry[4])()
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值