【C语言进阶】指针

2022-04-02-

摘要

指针的进阶

  1. 字符指针
  2. 数组指针
  3. 指针数组
  4. 数组传参和指针传参
  5. 函数指针
  6. 函数指针数组
  7. 指向函数指针数组的指针
  8. 回调函数
  9. 指针和数组面试题的解析

总结

目录

指针的概念

  1. 指针是个变量,用来存储地址。
  2. 指针的大小只与是64位平台还是32位平台有关,与指针类型无关。
  3. 指针类型决定了指针的解引用权限和读取方式。
  4. 指针±正数与指针所指向类型数据的长度有关。

字符指针

在指针的类型中我们知道有一种指针类型为字符指针 char* ;
一般使用:

int main()
{
   
  	char ch = 'w';
  	char *pc = &ch;
  	*pc = 'w';
  	return 0;
}

还有一种使用方式如下:

int main()
{
   
  	const char* pstr = "hello sx.";//这里是把一个字符串放到pstr指针变量里了吗?
  	printf("%s\n", pstr);
  	return 0;
}

const char* pstr = "hello sx.";这段代码的意思实际是将"hello sx"的首地址赋值给pstr.,这样pstr就拥有了访问这个字符串的能力。

但很多人会陷入一个误区:认为"hello sx"字符串被整个放到了pstr中。

像这样" "中放入字符直接写出来的字符串的我们叫做常量字符串,它存储在静态存储区,字符串的内容不能更改,并且只有在整个程序结束后,常量字符串所使用的内存空间才会被系统回收。

所以使用直接收常量字符串的指针时,通常使用const修饰。

实际pstr与常量字符串的关系

image-20220412094732925

看一道例题:

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

image-20220412094742129

你可能感到奇怪,字符串明明时相同的,怎么str3、str4就不同了?

实际上:

char arr[] = "hello sx";
//先创建一块空间,然后将字符串依次放入数组中。

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当
几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化
不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。

注意:同一个程序中出现的相同常量字符串都是同一个,类似与python将常量字符串存储在内存池中。

指针数组

指针数组即元素类型为指针的数组。

我们可以使用指针数组模拟一个二维数组。

int arr1[3] = {
   1,2,3};
int arr2[3] = {
   2,3,4};
int arr3[3] = {
   3,4,5};
int* arr[3] = {
   arr1, arr2, arr3};
如果想访问arr[i]中的第下标为j的元素,可以使用 *(*(arr + i) + j).

同样可以使用数组下标的方式 arr[i] [j];

但这只是模拟二维数组,并不是真正的二维数组。

二维数组的空间是连续的,可是在这里一定是连续的吗?

二维数组的每一行的大小是相同的,这里一定相同吗?

答案是否定的,这里的arr1 、 arr2 、 arr3的地址空间是随机的,长度也并没有固定。

数组指针

数组指针:意为数组的指针。

那么当然这是一个指针,它是指向数组的。

内置类型的指针:

例如 int* p, double* p,来剖析它的结构。

p被 * 修饰代表p是指针,那么指向什么类型?==》int。

下面代码哪个是数组指针?

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?

先来看看最普通的类型。

int arr1[10];
//arr1与[10]先结合,代表arr1是个数组,那么剩下的就是数组元素的类型。

int *arr;
//arr与*结合,代表arr是个指针,那么剩下的就是指针指向的类型。

p1先与[10]结合,表示p是个数组。

将p1[10]去掉剩下的就是数组的元素类型。

显然,p1这是一个指针数组,数组的每个元素是指向int的指针。

p2先与*结合,代表p2是个指针。

再与[10]结合,代表指向的是十个元素的数组,那么剩下的就是数组的元素类型了。

p2是一个指针,指向有十个元素,每个元素是int的数组。

int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个
指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。
对数组名取地址
int arr[10];

arr&arr有什么区别呢?

arr是数组名,首元素地址。

&arr是个什么呢?

看代码:

int main()
{
   
  	int arr[10] = {
   0};
  	printf("%p\n", arr);
  	printf("%p\n", &arr);
  	return 0;
}

image-20220412094755093

两者的值是一样的,难道就一样吗?

继续看:

int main()
{
   
	int arr[10] = {
    0 };
	printf("arr = %p\n", arr);
	printf("&arr= %p\n", &arr);
	printf("arr+1 = %p\n", arr+1);
	printf("&arr+1= %p\n", &arr+1);
	return 0;
}

image-20220412094803043

都执行 + 1操作后就不同了,那么说明它们指向的类型长度是有差异的。

可以看到 &arr&arr + 1 相差了40个字节,是arr这个数组的长度。

说明&arr 指向的应该是一整个数组,因此一次跳过一个数组的长度,那么也就合理了。

数组指针的使用

那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。

上代码:

#include <stdio.h>
int main()
{
   
  	int arr[10] = {
   1,2,3,4,5,6,7,8,9,0};
  	int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p
  	return 0;
}

这样的用法多少显得我们有点不太聪明的样子,这根本无法体现数组指针的价值。

如下使用可以完美契合二维数组:

#include <stdio.h>
void print_arr1(int arr
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值