指针2

103 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情


2. 字符指针

能够指向字符数据的指针 形如这样的char* p 这里就讲比较难的地方吧!看下面这个代码

void pd(char* s1,char* s2)
{
	if (s1 == s2)
		printf("相等\n");
	else
		printf("不相等\n");
}
int main()
{
	char arr1[] = "abcef";
	char arr2[] = "abcef";
	pd(arr1,arr2);
	char* p1 = "abcef";
	char* p2 = "abcef";
	pd(p1,p2);
	return 0;
}

这里的arr1和arr2,p1和p2相等吗?看结果 在这里插入图片描述

arr1与arr2不相等,p1和p2相等。在数组储存数据时,即使储存的字符串相等也开辟不同的空间。但是p1,p2可不能储存"abcef"这样的常量字符串,它们只是储存了首字符的地址,所以p1和p2相等.并且p1,p2所指向内存的数据不能更改,因为初始化的常量字符串是不能更改的,可以这样写

	const char* p1 = "abcef";
	const char* p2 = "abcef";

3. 数组指针

数组指针本质上是指针,例如:

  int (*p)[5]
  *说明p是一个指针,指针指向一个数组,
  数组中有5个元素,每个元素是int类型

这里的p的类型为 int (*)[5] 类型。 这样使用,例子:

void f(int (*p)[5],int n)
{
	int i, j;
	for (i=0;i<5;i++)
	{
		for (j=0;j<5;j++)
		{
			*(*(p + i) + j) = 1;
		}
	}
}
int main()
{
	int arr[5][5]={1,2,3,4,5,6,7};
	f(arr,5);
	return 0;
}
  • 这里的二维数组名表示第一行数组的地址,数组的地址要用数组指针进行接收。

下面这个对应着内存布局: 在这里插入图片描述

4. 指针数组

指针数组本质上是数组。例如:

int *p[5]
根据运算符的结合性可知,
p先与[]结合,说明p是一个数组,数组里面有5个元素,
每个元素是int*类型,也就是指针指向int类型

给个简单的例子: 看代码:简单

int main()
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 4,5,6 };
	int arr3[] = { 7,8,9 };
	int* p[] = { arr1,arr2,arr3 };
	int i = 0, j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("%d ", p[i][j]);
		}
		printf("\n");
	}
	return 0;
}

5.数组传参和指针传参

🥳1️⃣数组名表示的含义

  • 一维数组名 一维数组名表示数组首元素地址
  • 二维数组名 二维数组名表示首行数组的地址 每一行的数组都有自己的名字,对与下面的代码arr2[0]为第一行数组的名字

sizeof(数组名)求的是整个数组的大小。 &数组名取出的是整个数组的地址 例子:看代码

int main()
{
	int arr1[] = { 1,2,3,4,5,6 };
	int arr2[][3] = { 1,2,3,4,5,6 };
	printf("%d\n",sizeof(arr1));求的整个数组的大小,单位字节24
	printf("%d\n", sizeof(arr2));求的整个数组的大小24
	printf("%d\n\n", sizeof(arr2[0]));求的是第一行数组的大小12

	printf("%p\n", arr1);首元素的地址
	printf("%p\n", arr1+1);第2个元素的大小
	printf("%p\n", &arr1);这个元素的大小
	printf("%p\n\n", &arr1+1);越过整个数组后的地址

	printf("%p\n", arr2);首行的地址
	printf("%p\n", &arr2 + 1);越过这个数组后的地址
	printf("%p\n", arr2[0]);首行首元素的地址
	printf("%p\n", &arr2[0] + 1);第二行数组的首元素的地址
	return 0;
}

在这里插入图片描述

  • 运行的结果 在这里插入图片描述

🥳2️⃣数组传参

  • 一维数组传参
f(int arr[])
{}
f(int arr[3])
{}
f(int* arr)
{}
上面这三种都可以,但是最后一种比较好,它能反应出数组名字为数组首元素地址,
像第1与第2种里面[]里面有没有数值的没有问题。
f1(int* arr1[])
{}
f1(int* arr1[3])
{}
上面这两种大家应该可以理解
f1(int** arr1)
{}
arr是数组名,表示首元素地址,每个元素是指针,即指针的地址要用二级指针接受
int main()
{
	int arr[3] = { 1,2,3 };
	int* arr1[3];
	f(arr);
	f1(arr1);
	return 0;
}

对于一维数组传参,上面的几种都正确。

  • 二维数组传参
f(int p[2][2] )
{}
f(int p[][2] )
{}
上面这两种都可以,也都可以理解,前一个数值可以省略,
但是第二个[]的数值不能去掉.
f(int(*p)[2] )
{}
二维数组名表示首行数组的地址,要用数组指针进行接收
int main()
{
	int arr[2][2];
	f(arr);
	return 0;
}

🥳3️⃣指针传参

  • 一级指针传参
f(int* p)
{}
int main()
{
	int a = 0;
	int* p = &a;
	f(p);
	return 0;
}

一级指针传参用一级指针进行接收

==思考==:形参为一级指针的时候,实参可以为什么样的类型 1️⃣实参可以为一维数组的数组名 2️⃣可以为一级指针

  • 二级指针传参
f(int** p1)
{}
int main()
{
	int a = 0;
	int* p = &a;
	int** p1 = &p;
	f(p1);
	return 0;
}

二级指针传参用二级指针进行接收

==思考==:形参为一级指针的时候,实参可以为什么样的类型 1️⃣实参可以为指针数组 2️⃣可以为二级指针 3️⃣可以为一级指针的地址