IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 4.C语言——指针 -> 正文阅读

[C++知识库]4.C语言——指针

指针

指针就是地址

主要说几个注意点

1.指针的类型必须一一对应,int型的指针就必须对应int型的变量

在这里插入图片描述
不是一一对应的话就会报错

2.指针的加法和减法

假如说是一个int型的指针,对指针进行+1或者-1,在地址上加减的是一个sizeof(int)

    char arr[3];
	printf("arr:\n%d\n%d\n%d\n", arr, arr + 1, arr + 2);
	char *parr[3];
	printf("parr:\n%d\n%d\n%d\n", parr, parr + 1, parr + 2);

在这里插入图片描述

1.指针对数字,注意是数字,进行加减,必须是连续的空间有意义,也就是数组,不连续得到空间上进行加减数字没有任何意义

2.两指针进行减法,指针没有加法!指针的减法=(地址1-地址2)/sizeof(类型)

在这里插入图片描述

3.注意千万别越界

在这里插入图片描述
为什么没有报错?

C语言非常重视运行时的效率,所以没有进行数组越界检查。(检查数据越界,编译器就必须在生成的目标代码中加入额外的代码用于程序运行时检测下标是否越界,这就会导致程序的运行速度下降)

数组越界后,会自动接着前面那块内存往后写,这样带来的将会是一系列安全问题。因为界外的内存不确定是否已经存放了东西,如果不凑巧存放着比较重要的数据,那么数组越界后将会把这块内存上的重要数据替换掉。

指针计算中易错表达式

int  arr[5] = { 1,3,5,7,9 };
int  *p = arr;

*++p:p先自 + ,然后 * p,最终为3——马上改变指针, * 下一个指针

*p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1] ————之后改变指针,*原数据,指针++

*(p++):效果等同于 * p++ ——之后改变指针, * 原数据,指针++

( * p)++:先 * p,即arr[0]=1,然后1++,该语句执行完毕后arr[0] =2——不改变指针,数据++

++ * p:先 * p,即arr[0]=1,然后再++,最终为2——不改变指针,++数据

总结:

只有++(*p),(*p)++,++*p使指针的位置不变,改变数组的原始数值,

其他的任何情况都是指针指数组的下一个,指针的位置+1


(感谢有个兄弟私信我说这里没讲清楚,如果有错误或者不清楚的地方欢迎大家提出)


3.指针和指针变量是两个不同的概念

指针:地址

指针变量:是一个指针变量,这个变量的值是地址

例子:

int a[10],这里的a可以看作是指针常量,值不能发生改变,所以a+=1和a++都是错误的,但是我们int *p=a,然后对p进行++操作就没有问题!这里的a可以看作是指针常量,值不能发生改变。但是我们的p是指针变量

4.指针作为函数参数

普通的值传递都是单项传递,传递指针过去则是双向传递

情况一:
在这里插入图片描述

在这里插入图片描述
我们的传递值就对应上面那张代码图。

再看看另外一种情况

在这里插入图片描述
这个地方为什么a,b的值没有改变。

在这里插入图片描述
也就是说,我们值改变了形参的指向,并没有改变实参的指向。

5.const和指针的关系

讲得很清楚了,可以看看,点击传送

6.二维数组和指针

行指针格式:int (*a)[5]

行指针,顾名思义就是指向一行的指针。那么哪里会用到行指针呢,用的最多的,那就是二维指针了,大家都知道,我们通常把二维指针看成一个行列式,但是它在内存中的排序却是和一维指针一样的。

比如组a[2][3]={{1,2,3}{4,5,6}},a是整个数组的首地址,同时也指向第一行元素,即a是一个行指针,它每加1,所指地址移动二维数组的一行,a+1指向第二行元素。

对a取*,即a指向第一行第一个数,(a+1)指向第二行第一个数,可见,对行指针取值就成了列指针,此时它还是个指针。它每加1,所指地址移动一个元素,*(a+1)+1指向第二行第二个元素,也可以写成a[1]+1。

a(也可写成a[0][0])就是这个二维数组第一行的第一个元素,(a+1)(也可写成a[1][0])就是第二行的第一个元素,((a+1)+1)(也可写成a[1][1])是第二行的第二个元素。可见,对行指针取2次*就成了某个元素的值了,而不再是地址。

有这样一个公式a[i][j]=((a+i)+j),应该就知道为什么了吧…

行指针还可以这样定义int (*p)[n],此处定义的p指针,每加1,移动n个地址位(针对不同二维数组定义不同的n值)比如下面的这段:

int main(void)
{
 int a[2][3] = {{1,2,3},{4,5,6}};
 int (*p)[3];
 p = a;
 p++;
 printf("%d",**p);
}

此段代码输出结果为4,p是个行指针,可以直接将a这个行指针直接赋值给它,此时p也指向二维数组的起始地址,即第一行。p++就会移动3个元素,从而指向第二行。用法同二维数组名a。

对于二维数组中,因为我们的操作中没有取一行这个说法,所以我们的*a的这个 * 的作用可以理解为指针转化,将行指针转化为列指针

7.函数指针和返回指针的函数

1.指针函数:

返回型 (*变量名)(形参列表)
{

}

2.返回指针的函数:

类型名 *变量名(形参列表)
{

}

8.写法汇总

int* a;//a是指向整形的指针;
int* a[5];//一维指针数组(这里存放着5个指向整形的指针),a指向第一个元素的地址,a+1指向第二个......(a[5]是一个指针数组);
int (*a)[5];//指向数组(这里每个一维数组含5个元素)的指针,a是第一个一维数组的首元素地址,a+1指向第二个一维数组的首元素地址......(a是数组指针);
int (*a)();//a是指向函数的指针(函数指针);
int *a();//函数的返回类型是int *,a只是一个函数名
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-09 17:27:32  更:2021-07-09 17:27:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 1:00:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码