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

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

指针 *** 作数组 指针 *** 作一维数组

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


数组名

代表这段内存首地址

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

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++中是错的

 下期我会整合一下关于内存的知识点,最后感谢您能阅读我的博客,谢谢。


<\u>

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/562315.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-01
下一篇 2022-04-01

发表评论

登录后才能评论

评论列表(0条)