C语言中的指针

目录

指针存在的意义是什么?

指针的概念

指针变量的声明

取地址运算符和间接寻址运算符

指针的初始化 

指针的算术运算

万能指针

野指针


指针存在的意义是什么?

指针是C语言中最基础、最重要的概念之一,它使得C语言成为一门强大的、高效的、灵活的编程语言。指针的存在使得C语言可以进行复杂的内存操作,能够更好地控制程序的行为,同时也能够实现高效的数据结构和算法。简而言之,指针是C语言的灵魂。

指针的概念

存储地址的变量就是指针变量,我们平常所说的指针其实就指的是指针变量。概念很简单易懂,但还是可以深挖的。先说明一下,地址的大小只与机器本身有关,与指针的类型无关。也就是说,指针无高低贵贱之分,char 类型的指针和 int 类型的指针在同一机器下一样大,在32位机器下是4个字节,64位机器下是8个字节。

可以看到,p1和p2中都可以存放着i的地址,并且没有报错。所以,我们可以得出一个结论:任意数据类型的指针都可以保存任意数据类型变量的地址。 也许有人会问,既然任意数据类型的指针都可以保存任意数据类型变量的地址,指针类型存在的意义是什么?下文讲到指针的运算是会详细说明。

指针变量的声明

对指针变量的声明与对普通变量的声明基本一样,唯一不同就是必须在指针变量名字前放置星号*,例如 int* p; 此处的 * 是指针声明符,对这句代码的解读为:*代表变量p是指针变量,int代表指针变量p指向的是int类型的变量。这种理解方式可以推而广之,下文讲到其他复杂类型的指针时会以同样的方式进行解释。

取地址运算符和间接寻址运算符

为了找到变量的地址,可以使用&(取地址)运算符。

int  x = 0;

int* p = &x;

上述例子就是通过&运算符找到变量x的地址,然后存到指针p中。x的地址存是存进去了,如何通过指针p找到x呢?C语言提供了间接寻址运算符 * (此星号与上文的星号代表着不同的含义),一旦指针变量指向了对象,就可以用*运算符访问存储在对象中的内容。

//接上文

printf("%d\n", *p);

这样就可以显示出x的值。取地址运算符&和间接寻址运算符*一取一拿,很容易让人想到这对运算符是互逆的,对变量使用&可以产生指向变量的指针,而对指针使用*则可以返回到原始变量。因次,i 与 *&i 等价。 

指针的初始化 

声明指针变量是为指针留出空间,但是并没有把它指向对象。例如下面的代码:

int* p;

在使用指针p前初始化时很有必要的,我相信总有人会好奇如果使用未初始化的指针会导致什么后果。下面是我在VS2019环境下做的测试。

可以看到,程序根本跑不下去。如果此时对指针p赋值会怎样?

 程序依然跑不下去。其实此处对*p赋值很冒险。因为如果p恰好具有有效的内存地址,对*p赋值会试图修改存储在改地址的数据。如果上述赋值改变的内存单元属于该程序,那么可能会导致出乎预料的行为,如果改变的内存单元属于操作系统,那么很可能会导致系统崩溃。还好编译器没让上述程序运行下去。其实,此处的指针p就是一个野指针

指针的算术运算

指针的算术运算常常与数组结合起来,那是因为数组元素的空间在内存中是连续存放的。

C语言仅支持以下三种格式的指针算术运算。

> 指针加整数

> 指针减整数

> 两个指针相减

先看看指针加整数的效果。

可以看到,p加一后跳过了4个字节,正好是跳过一个int类型。其他指针类型加整数这里就不举例了 。接着再来看看指针减整数的效果。

可以看到,指针减1后地址正好少了4个字节。下面将以图的形式更形象的展现指针加减整数的效果。

到这,就可以看出指针类型的意义了:指针的类型决定了指针在加减整数时一次向前或向后跳几个字节,也就是决定了指针每一步的步长。指针类型的另一个意义在于:每一次要从指针指向内存中读取几个字节。所以,建议什么类型变量的地址就用什么指针类型去指向。

最后是两个指针相减。

当两个指针相减时,结果的绝对值为指针之间的距离(用这两个指针间的元素个数来度量),因为不排除用小地址减去大地址,考虑到严谨性,前面在指针相减的结果上加了绝对值 。需要注意的是,只有两个指针指向同一数组时(或两个指针指向同一块空间时),把它们相减才有意义。

万能指针

void*

这个叫空指针类型,也叫做万能指针。之所以叫万能指针,是因为它可以保存任意类型变量的地址,同时它还可以接收任意类型的指针对它赋值。 但是,不能对万能指针进行解引用操作,因为它不知道一次从内存里读取几个字节。

野指针

野指针:指向不明确,或者说指向的内存是否有访问权限不明确,这样的指针称为野指针。

容易产生野指针的三种行为有:

> 未对指针进行初始化。指着在定义的时候,如果不对其进行初始化,那么它会指向随机区域。因为任何指针变量(除了static修饰的指针)在定义的时候是不会自动置空的,它的默认值是随机的。

> 指针的越界访问。例如在主函数外返回一个指向栈内存的指针,因为当函数调用结束后,函数栈帧会被销毁,即使返回了指向一定空间的地址,但是栈空间在销毁后还给了操作系统,当前程序可能已经没有权限使用那块空间了。

> 在释放指针指向的空间后没有对该指针进行置空。free掉malloc出来的内存后,free函数并不会对指针进行置空,需要程序员手动置空,如果不置空,该指针将指向一块没有访问权限的空间,成为野指针。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值