C语言进阶:指针的进阶(上)

本文详细讲解了指针的基础概念,包括指针类型、字符指针、指针数组、数组指针、数组与指针的传参,以及函数指针的创建和使用。通过实例分析了数组名、一级指针和二级指针在函数参数传递中的作用。
摘要由CSDN通过智能技术生成

首先 在学习新知识之前 我们先来回顾下之前的学习的内容

1 指针是个变量 用来存放地址 地址唯一标识的一块内存空间
2 指针的大小是固定的4/8字节(32位平台/64位平台)
3 指针有类型的 指针的类型决定了两点 一个是指针操作的权限以及±整数的步长
4 指针的运算

一、 字符指针

1. 解析

在指针的类型中我们知道有一种指针的类型位字符指针

char *

我们一般这么使用

还有一种使用方式如下

这里我们存放的p其实不是一个字符 而是一个字符串的首地址

我们打印字符串的时候只需要把首地址传进去就可以打印出来一个完整的字符串

2. 题目巩固

我们来分析下
str1和str2是两个数组 相同的常量字符串去初始化 不同的数组会开辟不同的内存块 所以str1和str2不同
str3和str4是指向同一个常量字符串并且字符串不能被修改会储存在单独的一个内存区域 所以说str3和str4相同
我们打印出来看看 

二、指针数组

在指针章节中我们也学习了指针数组 指针数组是存放指针的数组

这里我们再复习一下 下面的指针数组是什么意思?

int *arr1[10]
一个指针数组 里面存放的int类型的指针
char *arr2[4]
一个指针数组 里面存放的是char类型的指针
char **arr3[5]
一个二级指针数组 存放的二级指针

例: 

 三、 数组指针

1. 数组指针的定义

我们先来看两段代码

int* p[10];//1
int(*p)[10];//2

因为1中的变量名先和p结合 所以说它是一个数组
因为2中的解引用标识符先和p结合 所以说它是一个指针

2. &数组名和数组名的区别

 先看代码

对于这段代码来说 arr和&arr分别是啥?
(其实这一段已经在我们前面的数组详解中已经介绍过了 我们再来复习下)

我们都知道arr是数组名,数组名表示数组首元素的地址

那么&arr数组名到底是啥?

&arr步进的地址实际上是40

arr步进的地址实际上是4

3. 数组指针的使用

 看代码

4. 总结

我们来逐个分析下 下面代码的意思

int arr[5]
int *p[10]
int (*p)[10]
int (*p[10])[5]

第一 是一个数组 数组里面有五个元素 每个元素都是int类型的

第二 是一个数组 数组里面有十个元素 每个元素都是整型指针类型的

第三 是一个指针 指针指向一个数组 数组里面有十个元素

第四 是一个数组 数组里每个元素类型是数组指针 每个数组指针指向的数组有五个元素

四、 数组传参 指针传参

void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test2(int *arr[20])
{}
void test2(int **arr)
{}

int main()
{
	int arr[10] = { 0 };
	int* arr2[20] = { 0 };
	test(arr);
	test2(arr2);
	return 0;
}

我们说test传参的时候 arr[10]都是可以传递进去的 因为传递数组本质上是传递一个地址

而对于test2来说 arr2传递是本质也是一个数组 数组里面存放的都是指针
所以说*arr[20]是可以传递的
对于最后一个二级指针来说 我们传递进去的是一个一级指针的数组 本质是把一级指针的地址传递进去 用二级指针来接受 当然没有问题

2. 二维数组的传参 

void test(int *arr)
{}
void test(int *arr[5])
{}
void test(int (*arr)[5])
{}
void test(int **arr)
{}
int main()
{
	int arr[3][5] = { 0 };
	test(arr);
	return 0;
}

 第一个指针指向整型 而我们的二维数组的地址实际上表示一行的所有元素 所以显然不行
第二个是一个数组 而我们要传递一个指针进去 显然不可以
第三个是一个数组指针 每一个指针指向五个元素 和我们的数组相符 所以可以传递进去
第四个是一个二级指针 指向的要是一级指针的地址 这里显然不行

3. 一级指针的传参 

void print(int* p, int sz) 
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d\n", *(p + i));
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(p, sz);
	return 0;
}

 一级指针的传参其实没什么花里胡哨的 直接把指针传进去就可以了
我们主要思考的是 当一个函数的参数部分作为一级指针的时候 函数能接收什么参数呢
我们说 可以传递
1 一维数组的数组名
2 一维数组地址
3 一级指针

 4. 二级指针的传参

代码和一级指针差不多 大家可以模仿者写一下 传参其实也没有什么花里胡哨的东西
还是一样的问题
当一个函数的参数部分作为二级指针的时候函数能够接收什么参数呢

1 一级指针的地址
2 二级指针
3 指针数组的数组名 (ex:int *p[5])

因为此时的p是一个数组 数组里面五个元素都是一级指针

当我们传递这个数组名的时候实际上是传递的首元素的地址 也就是说一级指针的地址

当然可以被二级指针接收啦

 五、函数指针

看代码

 1. 函数指针的创建

2. 函数指针的使用

解引用操作符可用可不用 对于结果没有影响

 很直观的就能看出函数指针的使用

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值