C语言学习笔记【02】——指针及其本质(二)

目录

指针操作数组

指针操作一维数组

指针操作二维数组

二级指针


指针操作数组

指针操作一维数组

在介绍之前,我们先了解一下关于数组名的知识。

数组名

代表这段内存首地址

回忆一下指针的定义,这数组名不就是指针吗,我们试着操作一下

int array[3]={1,2,3};
for(int i=0;i<3;i++)
    {
        printf("%d\t%d\n",array[i],*(array+i));
    	printf("%p\t%p\n",&array[i],&*(array+i));
    }

 可以看到,数据和地址都一致。

//对于array(数组名)
//正常操作: 直接存储数组的首地址
//直接把指针当作数组名就可以了
//非正常操作:指向其他元素开始操作数组

所以,对应指针(一级指针)也可以操作数组

int array[3]={1,2,3};
int* p=array;
for(int i=0;i<3;i++)
{
    printf("%d\t",p[i]);//对于这种方法我比较推荐,好理解,也可以用指针偏移
    //printf("%d\t",*(p+i));
}
ptintf("\n");

*p等效于p[0] 取当前地址对应内存中的值

 但是数组名的地址是不能更改的,这也是与指针的区别

	int test[3] = { 1,2,3 };
	int* pT = &test[2];
	printf("%d\n", pT[0]);//指针的[0]并不指数组第几个元素
	printf("%d\n", pT[-1]);//pT[-1]等效于*(pT-1)
	printf("%d\n", pT[1]);//未知量,垃圾值

指针操作二维数组

一级指针操作二维数组

  • 二维数组(举例为array[2] [3])在内存中是连续的,而二维数组的数组名是个数组指针(数组指针的首地址)。

  • 对于每行的首地址为数组名[i],例: array[i]

  • 使用数组名的偏移方式与一维数组不太一样

光看着可能不太明白,我们直接操作

int array[2][3]={1,2,3,4,5,6};
int* p=&array[0][0];
/*
注:
二维数组的类型为:int (*)[3],即数组指针
所以数组名(二维数组)是个指向数组的指针,不是一级指针
*/
printf("%p\n",array);
printf("%p\n",&array[0][0]);
printf("%p\n",array+1);
printf("%p\n",p+1);

 粗略分析一下

  • array与&array[0] [0]输出的值相同,即两者地址相同

  • (array+1)-array 的值为C(0x64-0x58=0xC,转十进制为12,即12个字节),正好是一行元素所占字节数

  • 同理,p+1对于p(即array[0] [0]) 偏移了4个字节(0x5c-0x58=0x4)

所以对于二维数组不能直接用数组名赋给一级指针

直接点就是,有几个元素就加几

array[i] [j]==*(p+n) (n=i *每行元素个数+j)

for(int i=0;i<6;i++)
{
    printf("%d\t",*(p+i));
}
printf("%d\n",array[1][2]);
printf("%d\n",*(p+(1*3+2)));

数组指针操作二位数组

数组指针

  • 指向数组的指针

  • 定义时,括号不能少

  • 只要指向首地址,可以直接当作数组名使用

int array[2][3]={1,2,3,4,5,6};
int (*pArray)[3]=NULL;//(*pArray)可以理解为数组名
pArray=array;
for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d\t", pArray[i][j]);
		}
		printf("\n");
	}

 还有不一样的用法(不推荐)

for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d\t", *(*(pArray + i) + j));//或者printf("%d\t",*(pArray[i]+j));
            //printf("%d\t",*((pArray+i)[0]+j));
            //printf("%d\t",((pArray+i)[0]+j)[0]);
        }
    printf("\n");
	}

 数组指针也可以作为函数参数

void printArray(int (*p)[3],int row,int col)
//等效void printfArray(int p[][3],int row,int col)
{
    for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			printf("%d\t", p[i][j]);
		}
		printf("\n");
	}
}

指针数组

  • 指针数组也可以控制二维数组

  • 就是多个指针

  • 一般用于操作字符串

char str[3][20] = {"ILoveYou","IMissYou","abc"};
char* pstr[3] = {str[0],str[1],str[2]};
//每个pstr[i]都是一级指针
for (int i = 0; i < 3; i++)
{
    puts(pstr[i]);
}

二级指针

  • 用于存放一级指针的地址

  • 同,N级指针是用来存放N-1级指针的地址

  • 定义

类型说明符 ** 名称

int* p=NULL;
int** pp=&p;
//几个*就是几级指针

看一下实例

int a=1;
int* p=&a;
int** pp=&p;
printf("%d\t%d\n",*p,p[0]);
printf("%d\t%d\n",**pp,*pp[0]);//或者pp[0][0],类似于二维指针但不同于二维数组

不能纯粹地当作二维数组来用

有的编译器可以,但是在C++中是错的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值