带你重新认识指针(下)

目录

    真的猛士,敢于直面惨淡的人生,敢于正视淋漓的鲜血。这是怎样的哀痛者和幸福者?然而造化又常常为庸人设计,以时间的流驶,来洗涤旧迹,仅使留下淡红的血色和微漠的悲哀。在这淡红的血色和微漠的悲哀中,又给人暂得偷生,维持着这似人非人的世界。我不知道这样的世界何时是一个尽头!我们还在这样的世上活着;我也早觉得有写一点东西的必要了。 ——鲁迅

    本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues。

    https://github.com/midou-tech/articles

    点关注,不迷路!!!

    看完我上一篇指针的讲解之后很多同学反馈很不错,有网友给私信说之前在大学里面一直搞不懂指针的问题,说到指针都是云里雾里,老师讲的也是很难听懂 ,点击即可进入 指针(上)。也有很多网友表示非常期待指针下的文章,所以我就马不停蹄的继续写,下 主要讲解指针的特性以及指针安全问题。

    指针的特性

    指针和常量

     先说下什么是常量,常量就是不可变的量,一旦定义该常量,其值在整个程序生命周期都是不可变的,常量存放在虚拟地址空间的常量区。

     在C语言里面有两种定义常量的方法。

    • 使用const关键字 ,const 定义的是变量不是常量,只是这个变量的值不允许改变是常变量,带有类型。编译运行的时候起作用存在类型检查。

    • 使用#define预处理器, define 定义的是不带类型的常数,只进行简单的字符替换。在预编译的时候起作用,不存在类型检查。

     其实很多时候我们错误的以为常量就是const 修饰的变量,这个说法其实是有瑕疵的。

    指针常量

     很多网友在学习指针和指针的特性等问题上总是会绕进去,其实不要绕进去最重要的一点是 要把握住核心本质

     本质上是一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化

    1int num = 5;
    2int *const p = #  // p为一个常量,拥有常量的属性。
    3*p = 70;
    4int snum = 100;
    5int *sp = &snum;
    6p = sp;

     聪明的你一定看出上面代码有个地方会报错,是的 p 被我们声明为一个指针常量,此时指针p具有了常量的属性,其不能在改变指向,但是其指向的值是可以改变的。所以报错的代码是p = sp这句。

    常量指针

     常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。

    int const *p = #   //常量指针
    3const int *sp = #  4*p = 20
    6p = &snum;   //改变指向
    7sp = &snum;

     是不是又发现上面的代码有一处报错,你太聪明了,基本搞懂了常量和指针的本质。指针p和sp只是申明格式不同,本质完全一样。p被声明为一个指针,指向一个常量。换句话说就是一个常量的地址存放在指针p中。此时报错的就是*p = 20,因为常量是不可变的。

     到这里你基本掌握了常量和指针的关系,其实还是很简单的,也没大家在学校学的那么绕。接下来给大家在介绍一个进阶的关系。

    常量指针常量

     本质上是一个常量,该常量被一个常量指针指向。也就是说一个常量指针里面放置一个常量的地址,千万不要多看一眼这句话,你会被绕进去。

    5;   //一个不可变的常量
    int * //一个存放常量地址的常量指针

     千万不要绕进去了,其实认真理解了上面的指针常量和常量指针的问题,这个问题看起来会简单很多,就是一个常量,和一个常量指针。num是一个不可改变的常量,p只一个指针,该指针也是不可改变指向的。

     指针和常量这个问题在面试中会被问到,好好理解下,同时有助于你更好的理解指针。

    指针和函数

    函数指针

    什么是函数指针

     如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。

     函数指针的定义和普通指针不太一样。函数返回值类型 (* 指针变量名) (函数参数列表);

    bool(*p)(charint); 

     还是很简单的,这就知道怎么定义一个函数指针变量了,当然也有很复杂的函数指针变量,面试的时候面试官可能会问一些变态的面试题,比如:

    int (*(void (*)())0)();
    void (*signal(int ,1); word-wrap: inherit !important; word-break: inherit !important">void(*)(int)))(int

     不过还是那句话,要把握核心本质,函数指针的核心本质是:函数返回值类型 (* 指针变量名) (函数参数列表);

    函数指针使用

     很多人会说,搞这么难干嘛,平时有使用么?哈哈,还真的经常用到,尤其是标准库中用的那叫一个多,比如sort中的比较函数就是一个函数指针。

    指针作为函数参数

     用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着函数的结束而被销毁。

     这不得不使我想起一个经典案例,大学老师一定会讲的,而且当时也是很多同学一直半解的。

     1void swap(int a,int b){
    2  int tmp = a;
    3  a = b;
    4  b = tmp;
    5}
    6int main(){
    7  int x = 10;
    8  20;
    9  printf("swap before:%d,%d",x,y);
    10  swap(a,b);
    11  "swap after:%d,1); word-spacing: 0; word-wrap: inherit !important; word-break: inherit !important">12  return 0;
    13}

     是不是历历在目。。。

     这个简单的问题,要搞明白可以学到好几个知识点。第一个,函数栈问题;第二个,函数的参数传递是值传递还是地址传递;第三个,指针作为函数参数。不过我这里就不讲前面两个了,相信大家能来看指针问题说明前面基础知识都差不多了,要是你真的不会的话,你可以找龙叔我,我一定把你整明白,微信搜索公众号 龙跃十二 即可找到龙叔微信,同时有机会加入龙叔技术交流群,千万别错过喔。

    求点赞

    相关文章

    一.C语言中的static关键字 在C语言中,static可以用来修饰局...
    浅谈C/C++中的指针和数组(二) 前面已经讨论了指针...
    浅谈C/C++中的指针和数组(一)指针是C/C++...
    从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时...
    C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下...
    C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面...