zoukankan      html  css  js  c++  java
  • C开发系列-指针

    指针

    通过一段简单的程序,引入指针的概念

    #include <iostream>
    using namespace std;
    
    // changeValue函数的定义
    void changeValue(int n)
    {
        n = 10;
    }
    
    // 程序入口main
    int main(int argc, char *argv[])
    {
        int num = 1;
    
        changeValue(num);
    
        cout << num << endl; // 这里输出num = 1
    
        return 0;
    }
    

    程序执行第一行:定义了一个int类型的变量num,由于变量num是int类型,在内存中给变量num分配4个字节的存储空间。
    程序执行第二行:调用函数changeValue,此时该函数被加载进内存,函数changeValue压栈,形参声明了int类型的变量n,内存会给变量n分配4个字节的存储空间。调用changeValue传入是num变量,等价于将num存储空间的值赋值给了变量n。
    程序执行changeValue函数体:将变量n存储空间赋值了10。

    此时的内存图如下:


    程序执行输出num等价于以十进制打印内存中的变量num的存储空间的value。所以数据的结果是1。

    如果想在changeValue内部修改num的值,这时候指针上场了。

    指针是什么?

    指针也是一种数据类型,指针变量就是保存指向变量内存的地址。通过指针可以修改所指向存储空间的值。

    定义一个指针类型变量,修改指向存储空间的值。

    要指向变量的类型 *指针变量名;
    int *p; // 定义了一个指针变量p 将来指针变量p只能保存int类型变量的内存地址。
    int num = 2;
    p = &num; // 将int类型变量的num地址赋值给指针变量p
    *p = 10; // *p访问保存地址对应的内存空间,也可以说访问指针变量p所指向的存储空间
    

    了解了指针的本质之后对上面的程序进行修改

    #include <iostream>
    using namespace std;
    
    void changeValue(int *n)
    {
        *n = 10;
    }
    
    int main(int argc, char *argv[])
    {
        int num = 1;
    
        changeValue(&num);
    
        cout << num << endl; // 这里输出num = 10
    
        return 0;
    }
    

    此时的changeValue函数形参是一个指向int类型指针变量。可见如果想调用changeValue需要传入int类型的变量的地址值。形参指针变量保存的是变量num的地址值,通过*n可以访问所指向变量num的存储空间的value。

    多级指针

    开发中最多可能遇到的就是二级指针。根据上面介绍的指针本质我们可以推导出多级指针的使用

    int num = 10;
    int *p;
    p = &num; 
    *p = 10
    
    int* *pp;// 定义一个int *类型的指针变量pp,pp将来存储的是int *类型变量的地址
    pp = &p;  // 将int *变量p的地址赋值给变量pp
    **pp = 20;  // **pp等价于*(*pp) ,*pp访问的是所指向变量p的存储空间也就是变量num的内存地址。其实*pp等价于p,所以**pp等于*p, 最终访问的也是变量num的存储空间。
    
    int** *ppp;
    ppp = &pp;
    ***ppp = 50;
    

    多级指针的技巧:
    通过上图多级指针可以根据有多少个箭头层级就通过多个*来访问最终指向的存储空间。

    二级指针使用场景

    我们清楚通过指针我们修改说指向存储空间的数据。如果想在函数内部修改指针(修改指针的地址值)就需要函数的形参是指针的指针了。

    通过下面的代码,分析函数形参传递指针与指针的指针的区别

    #include <iostream>
    using namespace std;
    
    void changePointer(int *p)
    {
        *p = 10;
    }
    
    void changePointer(int **pp)
    {
        // 通过*pp等价于p 
        *pp = (int *)malloc(100);
    }
    
    int main()
    {
        int *buf = NULL;
        
        // 通过传递一级指针 在函数内部修改指针指向的空间数据
        changePointer(buf);
        
        // 通过指针的指针 在函数内部修改指针(修改指针保存的指向内存地址)
        changePointer(&buf);
    
        return 0;
    }
    

    上面的内存 可以通过下图来体现

    补充:对于上面的指向指针p的指针pp,int **pp = &p, *pp就等于p。 如果一个指针变量为NULL,控制台输出的地址为0x0。

  • 相关阅读:
    WPF概述(硬件加速及分辨率无关性)
    创建自己的Code Snippet(代码模板)
    [LeetCode]46. Restore IP Addresses复原IP地址
    [LeetCode]45. Reverse Words in a String按单词翻转字符串
    [LeetCode]44. Implement strStr()实现strStr()函数
    [LeetCode]43. Integer to Roman整数转罗马数字
    [LeetCode]42. Roman to Integer罗马数字转整数
    [LeetCode]41. String to Integer(atoi)字符串转整数
    [LeetCode]40. Valid Palinadrome有效回文串
    [LeetCode]39. Longest Valid Parentheses最长有效括号对
  • 原文地址:https://www.cnblogs.com/CoderHong/p/8985695.html
Copyright © 2011-2022 走看看