指针详解(字符指针、数组指针,指针数组)

目录

字符指针

  习题检验(源于剑指offer)

指针数组

数组指针

使用数组指针打印数组元素

二维数组传参(用数组指针接收)

实践


字符指针

#include<stdio.h>
int main()
{
	char arr[] = "abc";
	char* p1 = arr;
	*p1 = 'r';
	printf("%s", arr);

	return 0;
}
#include<stdio.h>
int main()
{
	char* p2 = "abc";//p2指向的是a的地址
	*p2 = 'r';
	printf("%s", p2);

	return 0;
}

两代码执行结果如何呢?       

:第一个代码正常执行,第二个会报错。尽管 代码二的p2 存的也是首字符的地址,但是这种写法使“abc”成为常量字符串,所以不能进行修改。所以就出现了这种更为安全的写法:const char* p="abc"; (常量指针)

  习题检验(源于剑指offer)

#include <stdio.h>
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";

	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";

	if (str1 == str2)                    //数组名(首元素地址)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

 所以说:str3 与 str4 存的地址一模一样。

而 &str3 与 &str4 是不相等的,因为它们是两个不同的字符指针变量,不在同一个空间,当然不同,千万别把它们看成数组名了。


指针数组

问:指针数组是指针还是数组呢?           

:是数组,指针只是这个数组存放数据的类型而已,存放的是指针,即指向指针的数组。

#include<stdio.h>
int main()
{
	int a = 1;
	int b = 2;
	int* arr[] = { &a,&b };//指针数组存放指针(地址)

	return 0;
}

这就是指针数组的创建。那么该说说使用了:(模拟二维数组)

 但是这三个 arr 数组并不是连续存放在内存中的,ptr指针数组存的内容是连续存放的。


数组指针

提到了指针数组,那么就必须谈谈它的好兄弟了——数组指针。

数组指针是一个指向数组的指针(存放数组的地址),类型取决于数组的类型。

int arr[5];
//arr是整型数组,该如何存放。
//数组指针
int(*p)[5]=&arr;//p表示是一个指针,所以要先括起来,int[5]是arr的类型

//对于一个变量来说,去掉变量名就是变量类型
//所以上面的数组指针的类型:int(*)[5]

那么int* arr[5] 这个(指针)数组又该如何存放呢?

同理:int*(*p)[5]=&arr;


使用数组指针打印数组元素

我们知道用指针打印数组各个元素时,通过指针加1解引用就可以。

 因为在之间写的博客也提到过整型数组的指针加减1就是跳过一个一个整形的字节空间,解引用就相当于访问当前空间的数据。


那考虑考虑用数组指针来打印数组的各个元素,还可以直接加1嘛

#include<stdio.h>
int main()
{
	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
	int(*p)[10] = &arr;//创建一个数组指针p存放&arr,p的类型就是 int(*)[10]
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *((*p) + i));//
	}

	return 0;
}

那么该怎么理解  *((*p) + i) 呢?

数组指针p就相当于&arr,我们知道&arr取出的是整个数组的地址,加一就跳过一个数组类型的地址,在这里就是4*10个字节的空间。

*p就相当于 * &arr,那么*p 不就等价于arr(数组名,首元素地址嘛)那么((*p)+i)不就是(arr+i)嘛。

再次解引用不就得到各个元素嘛

而*((*p)+i)也可以写成(*p)[i]

这里只是介绍一下用数组指针打印数组各元素的方法,但是并不提倡哈。

二维数组传参(用数组指针接收)

在之前的三子棋和扫雷中我们见到了二维数组传参,形参也是一个二维数组的形式。

我们知道一维数组的数组名就是首元素的地址,那么二维数组的数组名呢——同样是首元素的地址。但对于二维数组来说首元素地址是第一行的元素地址。

int arr[2][3]={1,2,3,4,5,6};
//1 2 3 
//4 5 6
//而arr[0]与arr[1]就相当于两个一维数组的数组名,
//此时就可以把该二维数组看成一个一维数组。存的是arr[0]与arr[1]

//所以二维数组的数组名也就是arr[0]的地址,也就是第一行元素的地址。

有了这些了解,那么二维数组传参,传的是首行元素的地址,那么不就得用数组指针来接收嘛。

实践

#include<stdio.h>
void Print(int(*p)[3], int l, int r)//用数组指针接收,每行三个元素
{
	for (int i = 0; i < l; i++)
	{
		for (int j = 0; j < r; j++)
		{
			printf("%d ", (*(p + i))[j]);// *(p+i)表示的是第i行数组名(首元素地址)
		}
		printf("\n");
	}
}
int main()
{
	int arr[2][3] = { 1,2,3,4,5,6 };
	Print(arr, 2, 3);//二维数组名
	return 0;
}

 //这里也仅仅是了解一下这种写法,但是这种代码可读性差,不建议写,还是二维数组接收更佳。

猜你喜欢

转载自blog.csdn.net/C_Rio/article/details/129152008