C语言基础篇:指针

指针

指针的意思就是地址的意思。
指针变量其实就是一种变量,不过这个变量指的内容时地址。

Int a =10;
Int *p = &a;

通过上面两行代码,我们可以得出
有一个整型变量a,它的大小是10,还有一个指针变量p,它指向的是一个整型数a的地址。

*号的使用:

在定义指针变量时用一个*号表示这是一个指针变量。

Int *p;

给指针变量赋值时不带*

p=&a;

修改指针变量里的数据时,带*

*p=20

(这里的*p和定义时的*p不一样,这里的*p指的时指针变量p指向的地址里面的数据)

关于 * 和 & 的谜题

假设有一个 int 类型的变量 a,pa 是指向它的指针,那么*&a和&*pa分别是什么意思呢?

*&a可以理解为*(&a)&a表示取变量 a 的地址(等价于 pa)
*(&a)表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,
*&a仍然等价于 a。

&*pa可以理解为&(*pa),*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa。

二级指针(指向指针的指针)

指针变量也是一个变量,也有自己的地址,也可以被另一个指针变量指向。

比如:int a;
Int *p=&a;
Int **q=&p;
指针变量p指向整型变量a的地址
指针变量q指向指针变量p的地址

比如 int ***str;可以叫做这是一个指向一个指向指针变量的变量的变量。(经典绕口令)
在这里插入图片描述
在这里插入图片描述

指针作为函数的参数

指针作为函数参数的主要目的

我们知道函数里修改的数据只会在函数内部修改,函数结束后也就都释放了,但是如果我们在函数内部想要修改函数外部的数据,我们就可以把函数外部的数据的指针作为函数的参数传到函数里面,这些在函数内部也可以操作函数外面的数据。

典型例子:交换两个数的值

在这里插入图片描述
在这里插入图片描述
结果显而易见,你传入一个指针,是把地址里的数据改了,也就是在内存中就修改了这个地址里面的值。而普通的交换,在交换完毕后就释放掉了。

指针函数(指针作为函数的返回值)

指针作为函数的返回值的函数称为指针函数。
指针作为函数的返回值需要注意的一点是,函数运行结束后会销毁在它内部的定义的局部数据,包括局部变量,局部数组,形参,函数返回的指针尽量不要指向这些数据,C语言不会保证这些数据一直有效,后续运行过程中可能会发生运行错误
在这里插入图片描述
在这里插入图片描述
这个第一个是因为存放n的内存还没有被占用,所以输出结果是对的。第二个的话多加了一行代码,可能内存就已经被占用了,所以就会输出奇奇怪怪的东西。

函数指针(指向函数的指针)

一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。指针数组

在这里插入图片描述

指针数组

如果一个数组里面的所有元素都是指针的话,那么这个数组叫做指针数组。
在这里插入图片描述

二维数组指针(指向数组的指针)

指针数组和数组指针的区别

前者是一个数组,数组内每一个元素都是指针。后者是一个指针,它指向的是一个数组,后者的意义和二维数组是一样的。不过用指针的形式表示的话就叫做二维数组指针。

Int *p[3];表示一个数组
数组名叫做p,它里面有三个元素
每个元素的类型都是 int * 也就是指针变量,指向的是一个整数型。 
Int (*p)[3]表示一个指针。它指向的是一个数组,数组类型是 int[3].
也可以叫做二维数组指针。
Int a[3][3]  与 int(*p)[3]=a;是等价的。
例如: int a[3][3]={{0,1,2},{3,4,5},{6,7,8}};
Int (*p)[3]=a;
所以*p等于二维数组a的第一行(a[0])数据的地址。
Int **p为维数组a的第一行第一个元素的(a[0])的数据
p+1 /p-1 都应该是从指向a[0][0]到a[1][0]。前进或者后退的是4*3=12个字节。

*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

*(p+1+1=第一行第一个元素的地址
**(p+1+1=a[1][1]=3;第一行第一个元素的数据
根据上面所述,得到以下结论:
a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) 
		== *(*(a+i)+j) == *(*(p+i)+j)

在这里插入图片描述

指针的总结

指针(Pointer)就是内存的地址,C语言允许用一个变量来存放指针,这种变量称为指针变量。指针变量可以存放基本类型数据的地址,也可以存放数组、函数以及其他指针变量的地址。

程序在运行过程中需要的是数据和指令的地址,变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符:在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、字符串名和数组名表示的是代码块或数据块的首地址;程序被编译和链接后,这些名字都会消失,取而代之的是它们对应的地址。
在这里插入图片描述

常见指针变量的定义

  1. 指针变量可以进行加减运算,例如p++、p+i、p-=i。指针变量的加减运算并不是简单的加上或减去一个整数,而是跟指针指向的数据类型有关。

  2. 给指针变量赋值时,要将一份数据的地址赋给它,不能直接赋给一个整数,例如int *p = 1000;是没有意义的,使用过程中一般会导致程序崩溃。

  3. 使用指针变量之前一定要初始化,否则就不能确定指针指向哪里,如果它指向的内存没有使用权限,程序就崩溃了。对于暂时没有指向的指针,建议赋值NULL。

  4. 两个指针变量可以相减。如果两个指针变量指向同一个数组中的某个元素,那么相减的结果就是两个指针之间相差的元素个数。

  5. 数组也是有类型的,数组名的本意是表示一组类型相同的数据。在定义数组时,或者和 sizeof、& 运算符一起使用时数组名才表示整个数组,表达式中的数组名会被转换为一个指向数组的指针。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_LiuChunJiang刘春江

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

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

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

打赏作者

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

抵扣说明:

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

余额充值