【C语言】超详讲解☀️ 指针是个什么针?(指针进阶篇)(讲解+代码演示+图解)

  在前面的指针是个什么针?这篇文章中已经写了指针的基础知识,然后通过这篇文章来对指针进行更深层次的理解

目录

 一、字符指针

 二、指针数组

三、数组指针

数组名和&数组名

数组指针的使用

四、函数指针

函数地址

函数指针创建

函数指针的使用

五、函数指针数组

六、指向函数指针数组的指针


 一、字符指针

 字符指针的创建也是挺简单的,char*类型一次最多可访问一个字节的空间

请看如下代码:

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

这就是指针的创建以及访问操作,运行结果如下:

 关于字符指针这边主要想说的就是下面这种情况

int main()
{
	char* p = "abcdef";
}

 这是将字符串"abcdef"存到了指针p里面了吗?

abcdef总共7个字节大小,而char*在32位平台才4个字节,是根本存不下的,所以不是直接将整个字符串存到了指针p里面

要注意这种写法是将这个字符串的首字符地址给了p

 

这种写法也还不太严谨,在有的编译器下是会报错的,再修改一下

int main()
{
	const char* p = "abcdef";
}

 二、指针数组

 顾名思义,指针数组就是存放指针的数组

再看看下面代码中的数组

int* arr1[6];     //整形指针的数组
char* arr2[8];    //一级字符指针的数组
char** arr3[7];   //二级字符指针的数组

下面创建整型指针数组

#include <stdio.h>
int main()
{
	int a = 0;
	int b = 1;
	int c = 2;
	int* arr[3] = { &a,&b,&c };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%d ", *arr[i]);
	}
}

这里是创建了一个整型指针数组,并对它进行了初始化,里面存放有a,b,c的地址,再通过解引用去打印出a,b,c

运行结果:

 如下图:

 

 这个数组里面每个元素都是一个整型指针

通过下面这段代码再加深一下理解

#include <stdio.h>
int main()
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 4,5,6 };
	int arr3[] = { 7,8,9 };
	int* arr[] = { arr1,arr2,arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 3; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
	return 0;
}

通过这段代码创建指针数组,并对它进行访问,打印操作

三、数组指针

数组指针是一个指针指向数组的指针,里面存放数组的地址

数组指针的形式如下:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;
}

这里的p首先和*结合,说明它是一个指针,指向的是什么呢?指向了一个数组,数组10个元素,每个元素的类型都是int

数组名和&数组名

数组名是数组首元素的地址,&数组名是取出整个数组的地址

请看如下代码:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	printf("%p\n", &arr);
	return 0;
}

运行结果:

通过这个运行结果会发现这三个打印出来的值是一样的

 那难道数组名和&数组名真的就一样吗?我们通过以下代码再来看看:

#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%p\n", arr);
	printf("%p\n", arr + 1);
	printf("%p\n", &arr);
	printf("%p\n", &arr + 1);
	return 0;
}

运行结果:

 可以看到在给&arr和arr分别+1之后打印出来的结果是不一样的,arr+1跳过了1个整形4个字节,而&arr+1是直接跳过了整个数组

数组指针的使用

数组指针的使用一般常用于二维数组

如下代码:通过数组指针来访问二维数组

#include <stdio.h>
print(int (*p)[5], int x, int y)
{
	int i = 0;
	for (i = 0; i < x; i++)
	{
		int j = 0;
		for (j = 0; j < y; j++)
		{
			printf("%d ", (*(p + i))[j]);
		}
		printf("\n");
	}
	
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };;
	//通过下面这个函数以指针形式来访问数组
	print(arr, 3, 5);
}

运行结果:

四、函数指针

函数指针就是指向函数的指针 ----存放函数的地址

函数地址

 我们可以先通过下面的代码来体验一下:

#include <stdio.h>
void test()
{

}
int main()
{
	printf("%p\n", &test);
}

运行结果:

这里打印出了函数的地址

要知道数组名表示的是数组首元素的地址,那么函数名会不会也是函数的地址呢?

 通过以下代码来验证一下:

#include <stdio.h>
void test()
{

}
int main()
{
	printf("%p\n", &test);
	printf("%p\n", test);
}

 可以看到打印出来的结果是一样的,所以就可以确定函数名表示函数的地址

函数名与&函数名都是函数的地址,没有区别

函数指针创建

如下代码:

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int (*ps)(int, int) = Add;
	return 0;
}

这里的*p说明ps是一个指针,后面的(int,int)说明这个指针是指向一个函数,前面的int说明这个函数的返回值是int

函数指针的使用

我们可以通过函数指针来调用所指向的函数

如下代码:

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

运行结果:

 其实我们把Add放在了ps里面,那么其实ps和Add应该是一样的,用到的*其实在这里并没有什么实际作用,我们也可以用下面的写法

int add = ps(1, 2);

五、函数指针数组

里面存放函数指针

如下代码:

int add(int x, int y)
{
	return x + y;
}
int sub(int x, int y)
{
	return x - y;
}
int main()
{
	//函数指针数组
	int (*pf[5])(int, int) = { add,sub };
}

以上代码中的就是函数指针数组

pf[5]表示它是一个数组,剩下的部分说明它里面的每个元素都是函数指针,所指向的函数都是两个int类型的参数,返回类型位int

函数指针数组主要用于转移表

之前在C语言实现简易计算器这篇文章中写了函数指针数组的用法,用转移表来实现简易计算器,欢迎大家阅读,这里就不再把那个代码搬过来了

六、指向函数指针数组的指针

这是一个指针,指针指向一个数组,数组里面的每个元素都是函数指针

因为指向函数指针数组的指针用的非常少,所以这里就不再展开介绍了

如下代码示例:


    int (*psa)(int, int);    //函数指针
	int (*ps[5])(int, int);   //函数指针数组
	int (*(*pps)[5])(int, int) = &ps;    //指向函数指针数组的指针

注意:这里怎么判断是哪一种类型的指针,主要还是看的是操作符的结合性与优先级问题

-----------------------------------------------------------------

-----------------C语言指针进阶部分完结-------------------

关于C语言,每个知识点后面都会单独写博客更加详细的介绍

欢迎大家关注!!!

一起学习交流 !!!

让我们将编程进行到底!!!

--------------整理不易,请三连支持------------------

  • 26
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言中的智能指针是一种自动管理内存的指针,可以帮助开发人员避免内存泄漏和悬空指针等问题。但是,C语言本身并没有提供智能指针的实现,需要程序员自己手动编写。 C++中的智能指针是用来管理动态分配的内存的类,它们使用 RAII(资源获取即初始化)技术来确保在指针超出作用域时,内存被正确释放。C++标准库中提供了两种智能指针:std::shared_ptr 和 std::unique_ptr。Boost库中也提供了类似的智能指针实现。 std::shared_ptr 是基于引用计数的智能指针,它允许多个 shared_ptr 指向同一个对象。每当一个新的 shared_ptr 被创建时,其引用计数会加1,每当一个 shared_ptr 被销毁时,其引用计数会减1。当引用计数为0时,对象被自动销毁。 std::unique_ptr 是一种独占式的智能指针,它不支持拷贝和赋值操作,但支持移动语义。unique_ptr 只能有一个指向同一对象的实例,当 unique_ptr 被销毁时,它所指向的对象也会被销毁。 Boost库中的智能指针实现与C++标准库类似,但提供了更多的选项和扩展功能。例如,Boost库中的 shared_ptr 支持自定义删除器,可以在对象销毁时执行自定义操作。此外,Boost库还提供了一些其他类型的智能指针,如 scoped_ptr 和 intrusive_ptr 等。 总体来说,C++标准库和Boost库中的智能指针实现都非常强大和灵活,可以大大简化内存管理和错误处理。程序员可以根据自己的需求选择最适合的智能指针类型

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_错错错

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值