【理解指针(四)】

一、指针数组

我们可以先来回顾一下整形数组和字符数组。

  1. 整形数组:

是存放整形的数组
在这里插入图片描述

  1. 字符数组:
    在这里插入图片描述

是指存放字符的数组

类比上面两个例子之后,我们可以知道指针数组就是存放指针的数组,指针数组的每一个元素都是用来存放地址(指针)的。

在这里插入图片描述

二、指针数组来模拟二维数组

首先我们需要知道数组名是指数组首元素的地址

#include<stdio.h>
int main()
{
	int str[] = { 1,2,3,4,5 };
	int str1[] = { 3,4,5,6,7 };
	int str2[] = { 5,6,7,8,9 };
	int* pa[3] = { str,str1,str2 };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", *(*(pa + i)) + j);
		}
		printf("\n");
	}
	return 0;
}

我们可以得到如下的结果:
在这里插入图片描述
第一次的for循环是循环的行,第二次的dor循环也就是列,数组名就是数组的首元素,我们这里的pa[i]找到数组元素指向的是整形一维数组,pa[i][j]就是指向整形一维数组的元素。

模拟出⼆维数组的效果,实际上并非完全是⼆维数组,因为每⼀行并非是连续的

画个图方便大家理解:
在这里插入图片描述

三、字符指针变量

我们知道字符指针是char*
常如下使用:

#include<stdio.h>
int main()
{
	char p = 'e';
	char* s = &p;
	printf("%c\n", *s);
	*s = 't';
	printf("%c\n", *s);
	return 0;
}

结果会分别打印出:e 和 t 。

当然还有其他适用方式:

#include<stdio.h>
int main()
{
	char str[] = "hello world!!!";
	char* pa = str;
	printf("%s\n", pa);
	return 0;
}
注意:

这里的hello world!!!并没有放在指针变量pa中,而是把这个字符串的首字符的地址放在了pa中。
在这里插入图片描述
pa也就是调用字符串中首字符的地址,而字符串的地址也是首字符元素的地址。

字符串的例子(曾经的一道笔试题)

#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;
}

这题的答案是str1 and str2 are not samestr3 and str4 are same

我们大致来分析一下:

str1str2都是存的相同的字符串内容,在内存中str1str2是开辟了不同的空间存放相同的内容的,实质上完全没有必要存相同的内容开辟两个空间,两个空间的地址完全不一样,所以会打印出str1 and str2 are not same;而str3str4指向的是⼀个同⼀个常量字符串,C/C++会把常量字符串存储到单独的⼀个内存区域,指针指向同⼀个字符串的时候,他们实际会指向同⼀块内存,所以这里会打印出str3 and str4 are same

四、数组指针变量

1、什么是数组指针变量

首先我们可以来回顾一下:整形指针变量和浮点型指针变量

  1. 整形指针变量:
    存放的是整型变量的指针,能够指向整形数据的指针。
    形如:int* pa

  2. 浮点型指针变量:
    存放的是浮点型变量的指针,能够指向浮点型数据的指针。
    形如:float* pa

那么数组指针变量就是存放的是数组的地址,指向数组数据的指针。
形如:int(*p)[10]

这里的p是自己命名,10 也是根据自己写的代码来写。
p先和*结合,所以p是一个指针变量,指向的是一个大小为10个整形的数组。

综上:p是一个指针,指向一个数组,这就是数组指针。

2、数组指针怎么初始化

数组指针变量是⽤来存放数组地址的

int arr[5]={0};
&arr得到的就是数组的地址
int (*p)[5]=&arr//这个数组的地址存放在数组指针变量中

在这里插入图片描述

五、二维数组传参的本质

(二维数组我们可以看成许多一维数组的组成)

首先我们知道数组名是数组首元素的地址,那么⼆维数组的数组名表示的就是第⼀行的地址,也就是一维数组的地址,⼆维数组传参本质上也是传递了地址,传递的是第一行这个⼀维数组的地址
在这里插入图片描述
我们形参用指针写的形式如下:

#include<stdio.h>
void Shuzu(int(* pa)[5], int a, int b)
{
	for (int i = 0; i < a; i++)
	{
		for (int j = 0; j < b; j++)
		{
			printf("%d ", *(*(pa + i) + j));
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15} };
	Shuzu(arr, 3, 5);
	return 0;
}

当然形参我们也可以数组的形式写:

#include<stdio.h>
void Shuzu(int p[][5], int s, int c)
{
	for (int i = 0; i < s; i++)
	{
		for (int j = 0; j < c; j++)
		{
			printf("%d ", p[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15} };
	Shuzu(arr, 3, 5);
	return 0;
}

六、函数指针

1、什么是函数指针变量

通过上面的种种类比我们知道了什么是数组指针,整形指针,那么我们可以知道函数指针变量就是用来存放函数地址的。

2、函数的地址

首先我们可以简单的写一个代码,看看函数是否有地址:

#include<stdio.h>
void Ad()
{
	printf("abder\n");
}
int main()
{
	Ad();
	printf("&Ad=%p\n", &Ad);
	printf("Ad=%p\n", Ad);
	return 0;
}

在这里插入图片描述
由结果我们可以知道函数有地址,函数名就是我们的地址

如果我们要将函数的地址存放起来,就得创建函数指针变量:

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
	int(*pa)(int , int ) = Add;//&Add

在这里插入图片描述
其中==int(*)(int,int)==就是pa函数指针变量的类型。

3、使用

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int (*pa1)(int ,int) = Add;
	printf("%d\n", (*pa1)(2,4));
	printf("%d\n", pa1(5,6));
	return 0;
}

可以得出答案是6和11。

为什么第二个打印pa1可以不解引用?

因为pa1这个指针变量存放的是Add的地址,&符号与*相互直接抵消了,所以可以不使用解引用符号。

4、 typedef关键字

typedef是用来类型重命名的

比如:

singed int 可能你觉得每次书写比较麻烦,你就可以直接有时候typedef来重命名
也就是:typedef singed int ty_t,这个时候,想要再使用singed int 就可以直接用ty_t替换,
本质上是一样的

1.但是函数指针的重命名有些许区别:

比如,我们想要把int(*pa)(int )重命名为pa_t:

typedef int(*pa_t)(int);  //新类型的名字必须在*号的右边

2.数组指针重命名也是如此:

比如:我们需要把int(*pc)[10]重命名为py_y

typedef int(*py_y)[10];  //新类型的名字也需要在*号的右边

结束语

这次的内容可能有些多,但是比较好理解,希望大家可以拿到自己想要的offer,最后,如果文章有什么打错字的地方,希望大家不要介意,也希望大家可以给我提出来。
最后,祝大家每天都开开心心,我们下次再见
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值