首页 > 其他分享 >深入理解指针(3)

深入理解指针(3)

时间:2024-07-24 19:28:26浏览次数:17  
标签:变量 int 理解 深入 数组 test 函数指针 指针

一、字符指针变量

字符指针变量一般用char*来表示

一般使用:

#include"stdio.h"
int main()
{
    char ch = 'w';
    char* pc = &ch;
    *pc = 'w';
    return 0;
}

还有一种使用方法:

#include"stdio.h"
int main()
{
    const char* pc = "hello bit.";
    printf(%s\n",pc);
    return 0;
}

代码 const char* pc = "hello bit.";特别容易让我们以为是把字符串hello bit放到字符指针pc里,但是本质上是把字符串hello bit.首字符的地址放到了pc里。

二、数组指针变量

2.1数组指针变量是什么?

数组指针变量是指针变量

我们已经知道:

  • 整型指针变量:int * pc;存放的是整型变量的地址,能够指向整型数据的指针。
  • 浮点型指针变量:float * pa;存放浮点型变量的地址,能够指向浮点型数据的指针。

那数组指针的变量应该是:存放的应该是数组的地址,能够指向数组的指针变量。

数组指针变量:

1   int (*p)[10];

解释:p先和*结合,说明p是一个指针变量,然后指针指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫做数组指针

注:[]的优先级要高于*号,所以必须加上()来保证p先和*结合。

2.2数组指针变量怎么初始化

如果要存放数组的地址,就得存放在数组指针变量中:

1  int arr[10] = {0};
2  int (*p)[10] = &arr;

数组指针类型解析:

int (*p) [10] = &arr;
 |     |     |
 |     |    p指向数组的元素个数
 |    p是数组指针变量名
p指向的数组的元素类型

三、二维数组传参的本质

#include"stdio.h"
void test(int a[3][5], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			printf("%d ", a[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} };
	test(arr, 3, 5);
	return 0;
}

这里实参是二维数组,形参也写成二维数组的形式 

二维数组其实可以看作是每个元素是一维数组的数组,也就是二维数组的每个元素是一个一维数组。那么二维数组的首元素就是第一行,是一个一维数组。

根据数组名是数组首元素的地址这个规则,二维数组的数组名表示的就是第一行的地址,是一维数组的地址。。第一行的一维数组的类型是int [5] ,所以第一行的地址的类型就是数组指针类型     int (*)[5]。那就意味着二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址,那么形参也是可以写成指针形式的。

#include"stdio.h"
void test(int(*p)[5], int r, int c) 
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; 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} };
	test(arr, 3, 5);
	return 0;
}

 总结:二维数组传参,形参的部分可以写成数组,也可写成指针形式。

四、函数指针变量

4.1函数指针变量的创建

函数指针变量应该是用来存放函数地址的,未来通过地址能够调用函数。

#include"stdio.h"
int test()
{
	printf("hehe\n");
	return 0;
}

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

输出结果如下:

所以函数是有地址的,函数名就是函数的地址,当然也可以通过&函数名的方式获得函数的地址。

void test()
{
	 printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;
int Add(int x, int y)
{
	 return x+y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的

函数指针类型解析:

int    (*pf3)    (int x,int y)
 |        |       ___________
 |        |            |
 |        |           pf3指向函数的参数类型和个数的交代
 |       函数指针变量名
pf3指向函数的返回类型

int (*) (int x,int y) //pf3函数指针变量的类型   

 4.2函数指针变量的使用

#include"stdio.h"
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int(*pf3)(int, int) = Add;

	printf("%d\n", (*pf3)(2, 3));
	printf("%d\n", pf3(3, 5));
	return 0;
}

输出结果:

4.3typedef关键字

typedef是用来类型重命名的,可以将复杂的类型简答化。

比如:

1  typedef unsigned int uint;
2  //将unsigned int 重命名为uint

 但是对于数组指针和函数指针稍微有点区别:

将数组指针类型int (*) [5],重命名为parr_t,那就要写成:

1  typedef int(*parr_t)[5];//新的类型名必须在*的右边

函数指针类型的重命名也是一样的,将void(*)(int)类型重命名为pf_t,就可以这样写:

1  typedef void(*pf_t)(int);//新的类型名必须在*的右边

五、函数指针数组

要把函数的地址存到一个数组中,那这个数组就叫函数指针数组

1  int (*parr1[3])();

parr1先和[]结合,说明parr1是数组,数组的内容是int (*)()类型的函数指针。

标签:变量,int,理解,深入,数组,test,函数指针,指针
From: https://blog.csdn.net/L73S37/article/details/140656016

相关文章

  • 【精品资料】数据安全治理解决方案(27页PPT)
    引言:数据安全治理解决方案是一个综合性的体系,旨在通过策略、技术、流程和人力的有机结合,全面提升组织的数据安全防护能力,保障数据资产的安全与合规。方案介绍:数据安全治理解决方案是组织为确保其数据资产的安全性、合规性、完整性和可用性而实施的一系列策略、流程、技术和......
  • C++this指针--指针的介绍用法以及相关注意事项
    什么是this指针this指针是在C++中用来指向当前对象的特殊指针。它是每个非静态成员函数的隐式参数,指向调用该函数的对象。在C++类的成员函数中,除了静态成员函数外,每个成员函数都有一个隐含的this指针,它指向调用该函数的对象。这个指针可以让成员函数访问调用它的对象......
  • 深入剖析Tomcat整体架构
    目录Tomcat简介Tomcat架构概述核心组件详解ServerServiceConnectorEngineHostContextWrapper生命周期与初始化请求处理流程Tomcat的线程模型配置与优化常见问题与解决方案总结Tomcat简介ApacheTomcat是由Apache软件基金会开发的开源JavaWeb服务器和Servlet容器。它实......
  • 【算法专题】双指针算法之611. 有效三角形的个数(力扣)
    欢迎来到CILMY23的博客......
  • 【算法专题】双指针算法之LCR 179. 查找总价格为目标值的两个商品(力扣)
     欢迎来到CILMY23的博客......
  • 既然内存不值钱,为什么java还要搞一个压缩指针?
    尽管当前内存的价格可能相对较为亲民,但Java引入压缩指针技术的原因并不单纯基于内存成本,而是出于优化内存使用、提升程序性能以及适应不同应用场景的综合考虑。在64位Java虚拟机(JVM)中,传统的指针占用8个字节(64位)。然而,对于大多数Java应用程序来说,实际上并不需要如此大的内存地......
  • 掌握时间与空间:深入探讨Golang中的时间戳与时区转换
    时间是我们生活的基石,而在计算机科学中,时间处理显得尤为重要。尤其是当你在处理分布式系统、跨时区应用和全球服务时,时间和时区的管理变得不可或缺。在这篇文章中,我们将以幽默和深入的方式探讨Golang中的时间戳与时区转换。时间的基本概念时间戳时间戳(Timestamp)是指从1970年1月......
  • 深入理解Java虚拟机:JVM高级特性与最佳实践-第三章-垃圾收集器与内存分配策略
    在java内存运行时区域中的各个部分中,程序计数器、虚拟机栈、本地方法栈3个区域随线程而生,随线程而灭,因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就不需要过多考虑如何回收的问题,当方法结束或者线程结束时,内存自然就跟随着回收了。但是Java堆和方法区这两个区域具有......
  • 简答理解【字符指针】,存放字符串首地址???
    2024-07-23笔记-5作者(Author):仟濹(网名)字符指针①定义指针的时候也赋值字符串为什么给一个指针赋值字符串的时候也可以打印出来整个字符串???//eg:char*p="abcdefg";printf("%s",p);//abcdefgputs(p);//同理printf("%s",p+1);//bcdefgputs(p+1);/......
  • 深入理解Java内存模型及其在多线程编程中的应用
    深入理解Java内存模型及其在多线程编程中的应用大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们来深入探讨Java内存模型(JavaMemoryModel,JMM)及其在多线程编程中的应用。一、Java内存模型概述Java内存模型(JMM)是Java虚拟机规范的一部分,定义了变......