C语言指针与数组的重点内容

预说明:指针就是地址(eg:int*p=NULL)(NULL空指针)由指针变量(p)接收,但习惯性可能把指针变量直接称作指针,文中可能出现这种说法时,请有所了解。

一.数组的易错点

一维数组本质是一块连续的内存空间,用来存储同种数据类型的数据。

多维数组本质同样是一块连续的内存空间,用来存储同种数据类型的数据,空间不是以矩形排列(二维数组),或立方体排列(三维数组),以此类推。(图示如下,二维数组在内存中的空间)

如图,数组arr[3][3]在内存中不是图一的形式,而是图二,所以二维数组实际是一段连续的内存空间,多维数组可类比相同。(存储时前一行尾部连接下一行首部)

二.数组名的理解

一维数组(int a[3]={1,2,3};)

1.a是对内存空间的映射,用人话讲就是给一块空间起个名字。

2.a可看作一个指针常量,指向首元素,数值上固定表示a[0]的地址。

3.&a的值是a[0]的地址,但本质是数组的总地址,存在数组指针中(后文有对其的讲解)

(int(*p)[3]=&a)

#include<stdio.h>
int main()
{
	int a[3]={1,2,3};
	printf("%p %p %p\n",a,&a[0],&a);
	printf("%p %p %p\n",a+1,&a[0]+1,&a+1);
	return 0;
}

结果如图,上一行打印地址证明a,&a,&a[0]的值都是相同的,下一行指针加1,a+1多了4是多了数组中的一个元素的字节数,等于多了一个int类型所占的字节数,所以多了4(涉及指针加减的知识),&a[0]+1等于多了一个int类型的字节数,所以多4,&a+1是多了一个数组的总空间字节数,相当于4个int类型的空间,所以多了12。

二维数组(int b[3][3]={0};)

1.b是对内存空间的映射,用人话讲就是给一块空间起个名字。

2.b可看作一个指针常量,指向首元素,数值上固定表示b[0][0]的地址。

3.&b的值是b[0][0]的地址,但本质是数组的总地址,存在数组指针中(后文有对其的讲解)

(int(*p)[3][3]=&b)

#include<stdio.h>
int main()
{
	int b[3][3]={0};
	printf("%p %p %p\n",b,&b[0][0],&b);
	printf("%p %p %p\n",b+1,&b[0][0]+1,&b+1); 
	return 0;
}

 结果如图,上一行打印地址证明b,&b[0][0],&b的值都是相同的,下一行指针加1,b+1多了12是多了数组中的一个元素的字节数,二维数组一个元素为一行,等于多了3个int类型所占的字节数,所以多了12(涉及指针加减的知识),&b[0][0]+1等于多了一个int类型的字节数,所以多4,&b+1是多了一个数组的总空间字节数,相当于3*3=9个int类型的空间,所以多了36。(此处内容实际不全,最后补充中有详细代码)

多维数组

前文提到,数组名是指向数组首元素的指针常量,二维数组的一个元素表示一行,可以看作一个一维数组,同理,三维数组一个元素是一个二维数组,n维数组一个元素是(n-1)维数组,且各数组名是指向其数组首元素的指针,所以二维数组数组名是一个指向一维数组的指针(int (*b)[3]),以此类推,n维数组数组名是一个指向(n-1)维数组的指针。

三.数组指针和指针数组

数组指针

eg:int (*p)[3]是数组的指针,个人理解为一次开辟了3个int类型的空间大小,其值是首个字节的地址,可理解为首个int类型指针的地址,指针加1后地址增加3*4个值,在前面一维数组的代码中进行了测试。

指针数组

可理解为一种特殊的数组,只不过里面存的东西由int char等类型的数据变成了相应的地址。

#include<stdio.h>
int main()
{
	int a=1,b=2,c=3;
	int*pa=&a;
	int*pb=&b;
	int*pc=&c;
	int *p[3]={pa,pb,pc};//也可将pa变成&a,都是地址
	printf("%d %d %d",*(p[0]),*(p[1]),*p[2]);
	return 0;//输出1 2 3
}

总结

int (*p)[3]为数组指针的格式(多维数组后加[n] (n为任意常量))

int *p[3]为指针数组的基本格式,多维数组同上解释

二者存在差异的原因是因为运算符优先级的问题。   () > [] > *   

四.指针模拟动态开数组

malloc函数介绍

malloc函数:申请一段空间,并返回该空间首地址

头文件:<malloc.h>or<stdlib.h>(ANSI建议用后者)

int *p=(int*)malloc(size_t);

void(相应类型)*p=(返回类型)malloc(申请空间字节数);

开一维数组

#include<stdio.h>
#include<stdlib.h> 
int main()
{
//开5个int类型大小的空间用来存数值
int*p=(int*)malloc(5*sizeof(int));
for(int i=0;i<5;i++)
{
	p[i]=i;//赋值0-4
}
for(int i=0;i<5;i++)
{
	printf("%d ",p[i]);//输出0-4
}
	return 0;
}

开二维数组

#include<stdio.h>
#include<stdlib.h> 
int main()
{
//开5个空间存5个一级指针 
int**p=(int**)malloc(5*sizeof(int*));
//每个一级指针开5个空间用来存数组中的值 
p[0]=(int*)malloc(5*sizeof(int));
p[1]=......
......//效果相当于int p[5][5]; 
	return 0;
}

五. 二维数组 数组名的补充 

#include<stdio.h>
int main()                 //为方便讲解,标上序号
{
	int b[3][3]={0};       // 1    2    3      4      5
	printf("%p %p %p %p %p\n",&b,  b,  &b[0],  b[0],  &b[0][0]);
	printf("%p %p %p %p %p\n",&b+1,b+1,&b[0]+1,b[0]+1,&b[0][0]+1); 
	return 0;
}

第一行运行结果说明序号1-5的值都是相同的。

结合上文(二 . 二维数组的内容),可将其分为(1)(2 3)(4 5) 共三组,每一组的本质是相同的,这里不做细致讲解,请结合上文内容理解。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值