c中指针简介

c中指针简介

首先我们来看一下指针的一些基本概念
![在这里插入图片描述](https://img在这里插入图片描述
而对于指针的应用,平常有一些形式,总结了一下大概有这几种用法
在这里插入图片描述
对于以上的几种用法,我依次给出详尽的解释
//这是一个普通的整型变量

1 //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针

2 //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组

3 //首先从P 处开始,先与[]结合,因为其优先级比高,所以P 是一个数组,然后再与结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组

4 //首先从P 处开始,先与*结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针**

5 //首先从P 开始,先与结合,说是P 是一个指针,然后再与结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.

6 从P 处起,先与()结合,说明P 是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数,然后再与外面的 int 结合,说明函数的返回值是一个整型数据

7 //从P 处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针**

8 //可以先跳过,不看这个类型,过于复杂从P 开始,先与()结合,说明P 是一个函数,然后进入()里面,与int 结合,说明函数有一个整型变量参数,然后再与外面的结合,说明函数返回的是一个指针,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数.**

接下来我们具体来看一些指针类型

字符指针

在这里插入图片描述
还有一种方式是把字符串的首地址放到字符指针中
在这里插入图片描述
那么会有这样的一个问题
在这里插入图片描述
上述程序的结果如下图,为什么不一样呢?
在这里插入图片描述
这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指
针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候
就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。

指针数组

在这里插入图片描述

数组指针

在这里插入图片描述
我们来看一段代码
在这里插入图片描述
他的运行结果为
在这里插入图片描述
所以我们会得出一个结论,那就是数组名和&数组名打印的地址是一样的
但是真的是一样的吗?
我们再来看一段代码
在这里插入图片描述
再来看看他们的打印的结果
在这里插入图片描述
那么为什么会这样呢?
其实,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。所以&arr+1其实是取了整个数组的地址并跳过了整个数组
数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40.

数组指针具体如何使用,用一个代码来具体体现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
指针除了上述的一些引用外,最主要的是用于函数的参数
数组参数,指针参数
一维数组传参
在这里插入图片描述
在这里插入图片描述
以上的形式都是合理定义参数的方法
二维数组传参
在这里插入图片描述
一级指针传参
在这里插入图片描述
二级指针传参
在这里插入图片描述
我们来看一下一段代码

在这里插入图片描述
我们可以看,第一次调用时传的时pc指针的地址,而本身pc这个变量是(char *)类型,所以传pc的地址,就需要用char **来接受,而第三次传参时,因为arr是一个指针数组,它每一个元素存的是一个指针,但传它的数组名,也就是传首元素的地址,其实也就是一个一级指针,所以传它的地址也就是传二级指针,所以没有问题。

函数指针

在这里插入图片描述
运行结果为
在这里插入图片描述
输出的是两个地址,这两个地址是 test 函数的地址。 那我们的函数的地址要想保存起来,怎么保存?
我们就可以用函数指针
在这里插入图片描述
首相要存地址,必须是指针,所以pfun1可以,因为pfun1先和*结合再指向一个函数,函数无返回值。

函数指针数组

那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
在这里插入图片描述
首先parr1先和【】结合,说明parr1是数组,数组的内容是什么呢? 是 int (*)() 类型的函数指针
函数指针数组的用途:转移表

指向函数指针数组的指针

指向函数指针数组的指针是一个 指针 指针指向一个 数组 ,数组的元素都是 函数指针 ;
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383427.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

判断一个字符串是否另一个字符串的右移后的

首先我们把需要判断的字符串传进来,开辟一块大小为两个字符串的长度总和加1的动态的空间,然后后字符串拷贝函数将一个字符串拷贝到开辟空降中,再将这个字符串再次连接到这块动态的空间中,等于就是将一个字符串拷贝了两遍。然后比较…

不带头结点的链表基础操作(初始化,增删改查)

链表是什么? **链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括…

链表面试题1:反转单链表,不带头结点。

三个指针p1,p2,p3,p1指向头结点的前一个结点,也就时指空,p2指向头结点,p3指向头结点下一个结点。 p3指向p2的下一个,让p2指针域指向p1,让p1挪到p2上,再让p2指向p3.

链表面试题2:编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

我们可以,用两个新链表,一个存比基准值大的,另一个存比基准值小的。然后再拼接在一起。 用尾插的方法,首先说小的,创建两个指针,一个头,一个尾,再创建个指针跑链表,扫描…

栈和队列的基本操作(栈和队列的区别)

数据结构中的栈与内存中的栈的不同 一、数据结构中的堆栈 在数据结构中的堆栈,实际上堆栈是两种数据结构:堆和栈。堆和栈都是一种数据项按序排列的数据结构。 1.栈就像装数据的桶或箱子 我们先从大家比较熟悉的栈说起吧,它是一种具有后进先…

链表面试题3:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成 的。

链表面试题3:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成 的。 首先我们的思想是将得一个链表和第二个链表的每个结点进行比较,谁小谁就插入到新链表的最后。 首先我们要判段链表是否为空,…

双向链表的操作(创建,插入,删除)

双向链表的代码看似复杂,其实很简单,只要画图便可明白, 删除 假如要删除的结点叫pos. pos->prev->nextpos->next; pos->next->prevpos->prev; free(pos);

二叉树的操作(前,中,后序遍历也叫深度优先遍历,非空结点的个数)递归实现

定义一个二叉树的结点 二叉树的前序遍历, 先访问根结点,再访问左,再访问右。 每次访问都要先看根结点是否为空,然后打印根结点,把此时根结点的左结点作为下一次递归的根结点,当把左结点遍历完后&#xff0…

二叉树的相关题(叶子结点个数,最大深度,找特殊值结点(值不重复),判断两个树是否相同,判断两个数是否为镜像树,是否为子树,)

叶子结点就是没有孩子结点,所以当当前根结点没有孩子结点的时候,就返回1,就是找到一个叶子结点,然后访问完每个不为空的结点就行,每次访问都是把当前结点的左/右结点作为新的结点,来判断。 求最大深度&…

为何线程有PID?

在linux下用 top -H -p <pid> 查询某个进程的线程 按理说&#xff0c;都是某个进程下的线程&#xff0c; 应该进程id PID一样啊&#xff0c;但实际却都不一样 实际是被PID的名字给弄混了&#xff0c;线程进程都会有自己的ID&#xff0c;这个ID就叫做PID&#xff0c;P…

用c语言构建二叉树(重点)

结点创建 二叉树创建 我们以‘#’为NULL&#xff0c;我们要把输入进来的一个字符串转变为二叉树&#xff0c;所以我们要记住递归的每一步走到数组了哪个位置 所以我们要记住创建过程中用掉的前序个数&#xff0c;并返回&#xff0c;除此之外&#xff0c;还要加上当时的那个结点…

二叉树的广度优先遍历(层序遍历)

先定义一个二叉树的结点 再创建二叉树&#xff0c;这里就不写了&#xff0c;之前的有创建二叉树的博客。 层序遍历 用到栈的思想&#xff0c; 1 先让根 节点进队列&#xff0c;2 然后读队顶元素&#xff0c;3 让他出队列4 打印它的值5 让队顶元素的左右子树进栈&#xff0…

用前序中序创建二叉树(用中序后序创建二叉树)

定义二叉树结点 比如就拿这个二叉树 前序中序创建 因为前序遍历的顺序是 根 &#xff0c; 左 &#xff0c;右。 中序的遍历是 左 根 右。 我们会很不好想&#xff0c;但我们可以用前序和中序把上面那个二叉树的遍历一边 前序遍历&#xff1a;ABDEHCFG中序遍历&#xff1a;D…

Epoll详解及源码分析

文章来源&#xff1a;http://blog.csdn.net/chen19870707/article/details/42525887 Author&#xff1a;Echo Chen&#xff08;陈斌&#xff09; Email&#xff1a;chenb19870707gmail.com Blog&#xff1a;Blog.csdn.net/chen19870707 Date&#xff1a;Jan.7th, 2015 1…

非递归实现二叉树(前序,中序,后序)c/c++实现

这里还是用到栈的思想&#xff0c;为了方便用了c的一些内容&#xff0c;把出栈&#xff0c;进栈&#xff0c;读栈顶元素用一个个函数封装起来了&#xff0c;前面做了一些处理来使用这些函数。 前序非递归 思想&#xff1a;一直走左边&#xff0c;依次进栈。等左边为空的时候&…

Linux 中统计一个进程的线程数

如果你想看到 Linux 中每个进程的线程数&#xff0c;有以下几种方法可以做到这一点。 方法一: /proc proc 伪文件系统&#xff0c;它驻留在 /proc 目录&#xff0c;这是最简单的方法来查看任何活动进程的线程数。 /proc 目录以可读文本文件形式输出&#xff0c;提供现有进程和系…

Linux_linux基础命令(增删查,权限,Linux下的重要目录,重要命令(. du, df, top, free, pstack, su, sudo).安装gcc/g++, gdb, vim )

r&#xff1a;表示可读w&#xff1a;表示可写x&#xff1a;表示可执行也可以用数字表示这一点我们会在修改文件权限说明。对于文件夹的rwx表示&#xff1a;r表示可读及可以查看文件夹内容可以ls查看w表示可写及可以向文件夹中传送内容如文件x表示可执行及可以向文件夹中可以cd进…

Linux_linux常用工具之make/makefile详解

make/makefile make/makefile: 项目自动化构建工具 makefile:普通文本文件&#xff0c;记录了项目的构建流程规则。 make: 一个解释程序&#xff0c;到当前执行make命令的目录下寻找makefile文件&#xff0c;并且对makefile 中记录的项目构建规则进行解释执行。makefile: 编写…

Linux_linux常用工具(git,vim ,gcc ,gdb,权限)超详解

git :项目版本控制工具 项目克隆&#xff1a;git clone项目提交&#xff1a;git add&#xff08;本地仓库提交&#xff09; git commit -m “bak msg”&#xff08;-m 备注信息&#xff09;同步到服务器&#xff1a;git push origin master&#xff08;提交到主分支&…

Linux_linux常用工具------进度条程序

缓冲区对文件读写的影响&#xff1a;数据并没有直接写入文件&#xff0c;而是写入到缓冲区&#xff08;内存&#xff09;中&#xff0c;等到缓冲区中数据写满或者刷新缓冲区的时候&#xff0c;才会将数据真正的写入文件 fflush&#xff08;stdout&#xff09;刷新。 回车与换行…