C语言指针与数组理解

指针
32位机
C语言中指针是变量:
所以它有如下特点:
1.所占内存大小(4个字节 );
2.作用域
3.存储区域
而指针又有步长,当指针进行表达式运算时。其步长跟所定义指针的类型相关
如:char *p 步长为1 int *p 步长为4;
所以在进行不同步长指针赋值时,会出现数据错误。

延伸出另外一个知识点:大端字节序与小端字节序。
这是由不同cup决定的(inter大多数是小端字节序)
小端字节序:低地址放低字节,高地址放高字节
大端字节序:高地址放低字节,低地址放高字节
如int num = ox12345678; 78是低字节。
我们可以根据指针来判断机器是字节序:
int num = ox12345678
char *q = #
if(*q = ox78)
printf(“small”);
else
printf(“big”);

万能指针void *p可以保存任何类型的指针地址。对于void *类型的指针不可作取值运算,它所占的步长为1;占位字节;其中malloc分配的地址返回值也为void *类型

野指针
什么是野指针??如何避免它?
未初始化的指针,它随机指向一块内存(linux下未初始化的变量,系统随机分配),从而造成内存泄露,非法访问一块内存或者已经释放的内存。

避免:
首先要养成如下的编码习惯:
1.当定义一个指针时, 不确定它指向那,应该置为NULL;
2.往指针指向的空间进行赋值,要给指针分配空间(malloc函数);
3.判断分配好的空间是否分配成功
4.初始化分配好的空间
5.使用分配好的空间时不要出现越界
6.使用完应该使用释放函数释放分配好的空间
7.释放完再次置空指针。

其中free函数释放空间不能超过分配的空间,否则出现堆溢出

3种内存分配函数的区别:
realloc函数 追加分配空间,会对分配的空间初始化
malloc函数分配一块空间,但是不会对空间进行初始化
calloc函数不做初始化,分配几块连续的空间

数组:
理解一维数组,二维数组,三维数组名的含义:
一位数组名:是一个指针常量,它保存的是数组首元素的地址。所以对一维数组赋值还可以
scanf("%d", a+i); 其中i是循环变量;
&a 表示数组的首地址。其步长就为数组的大小 +1 相当于加一个数组。
a +1 加一个步长 4个字节(int a【3】);
对一位数组取值相当于数组首元素的地址:*(&a) = a;

int aa【2】【2】
**二维数组名:*是一个指针常量,它保存是二维数组中首个一维数组的地址。
对二维数组取值等于二维数组中首个一维数组的地址
(&aa) = aa;
再次取值 *aa = &a【0】【0】;
对于aa +i; 表示二维数组的第i个一维数组的地址
&aa + 1 表示加一个二维数组的步长
*aa + 1 表示加到下一个元素

所以二维数组赋值还可以
scanf("%d", *(*aa +i) +j)); i,j都是循环变量

int aaa[3][3][3]
三维数组名:是一指针常量,保存的是三维数组中首个二维数组的地址
对于三维数组取值等于三维数组中首个二维数组的地址 *(&aaa) = aaa;
再次取值 *aaa 表示三维数组中首个二维数组的首个一维数组的地址
再次取值表示 **aaa = &aaa【0】【0】【0】;
对于aaa + i 表示三维数组的第i个二维数组的地址
&aaa + 1 表示加该三维数组的步长
*aaa + 1 表示加到三维数组中下一个二维数组
**aaa + 1 表示加到下一个元素

扫描二维码关注公众号,回复: 9650217 查看本文章

数组的地址上述提到数组的地址
所以我们需要数组指针来保存数组的地址
int (*pa)[3] ;
其用法在于使用二维数组多维数组作为函数参数传递时:如我想传一个二维数组作为一个函数中
void func(int *(par)[3]) 相当于将int a[3][3]数组传入

指针数组:int *(pa[3]); 作用:
1.实现不规则多维数组
2.节省空间(传递多行数据时候,不需要拷贝大量数据,只需用指针,节省空间)

当我们需要传递一个指针数组作为函数形参时候,需要定义一个二维指针去接它
func(int ** s)
func(pa)

当我们函数传递一个数组时,编译器会自动将其变成指针

发布了23 篇原创文章 · 获赞 9 · 访问量 1690

猜你喜欢

转载自blog.csdn.net/weixin_42590177/article/details/90124245
今日推荐