• C语言 -- 指针


    一、变量的地址

    在C语言中,每定义一个变量,系统就会给变量分配一块内存,比如,定义一个 int num = 10; ,这样就会在计算机内存中开辟一块内存,来存放这个10,而这一小块内存是有地址的,我们可以通过这个地址,来找到里边的内容。如果把计算机的内存区域比喻成一个学校,那么每块内存的地址就像教室的门牌号。

    C语言采用运算符&来获取变量的地址。如下:

    int main()
    {
        int num1 = 10;
        char english = 'a';
        double price = 100.00;
    
        printf("%p
    ", &num1);
        printf("%p
    ", &english);
        printf("%p
    ", &price);
    
        system("pause");
    }
    

    结果:

    在printf函数中,输出内存地址的格式控制符是%p,地址采用十六进制的数字显示。

    二、指针

    指针是一种特别变量,全称是指针变量,专用于存放其它变量在内存中的地址编号,这样的一份数据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。指针在使用之前要先声明。

    现在假设有一个 char 类型的变量 c,它存储了字符 'K'(ASCII码为十进制数 75),并占用了地址为 0X11A 的内存(地址通常用十六进制表示)。另外有一个指针变量 p,它存储了 0X11A,正好等于变量 c 的地址,这种情况我们就称 p 指向了 c,或者说 p 是指向变量 c 的指针。

    定义指针变量的语法是:

    datatype *varname;
    

    或者

    datatype *name = value;
    

    “*”表示这是一个指针变量,datatype表示该指针变量所指向的数据的类型 。例如:

    int *count;
    

    count 是一个指向 int 类型数据的指针变量,至于 count 究竟指向哪一份数据,应该由赋予它的值决定。再如:

    int num = 100;
    count = &num
    //将num的地址给count

    将变量num的地址赋予给count,此时 count就指向了 num。取地址用的就是 &

    注意:不管是整型、浮点型、字符型,还是其他的数据类型的内存变量,它的地址都是一个十六进制数,可以理解为内存单元的编号。我们用整数型指针存放整数型变量的地址;用字符型指针存放字符型变量的地址;用双精度型指针存放双精度型变量的地址,用自定义数据类型指针存放自定义数据类型变量的地址。

    如下:

    int main()
    {
        int num1 = 10;
        char english = 'a';
        double price = 100.00;
    
        int *num2;
        num2 = &num1;
    
        char *enlist2;
        enlist2 = &english;
        
        double *price2;
        price2 = &price;
    
    }
    

    定义指针变量时必须带*,给指针变量赋值时不能带*,如下

    int main()
    {
        int num1 = 10;
        char english = 'a';
        double price = 100.00;
        
        int *num2 = &num1;
        char *enlist2 = &english;
        double *price2 = &price;
    
    }

    三、通过指针操作内存变量

    定义了指针变量,并指向了内存变量的地址,就可以通过指针来操作内存变量(在指针前加星号 *),效果与使用变量名相同。

    格式:

    *pointer;
    

    要取得指针所指向内存中的值,需要用*号,*称为指针运算符,用来取得某个地址上的数据,加上指针变量名称即可,如下:

    int main()
    {
        int num1 = 10;
        int *num2 = &num1;
        printf("%d
    ",*num2);
        printf("%d
    ",num1);
    }
    

    结果:

    假设 num1的地址是 0X1000,num2 指向 num1 后,num2本身的值也会变为 0X1000,*num2表示获取地址 0X1000 上的数据,也即变量 num1 的值。从运行结果看,*num2和num1 是等价的。

    CPU 读写数据必须要知道数据在内存中的地址,普通变量和指针变量都是地址的助记符,虽然通过 *num2 和 num1 获取到的数据一样,但它们的运行过程稍有不同:num1 只需要一次运算就能够取得数据,而 *num2 要经过两次运算,多了一层“间接”,因为*num2要先找到地址,然后取里边的值,而num1是直接取值。

    假设变量 num1、num2 的地址分别为 0X1000、0XC100,它们的指向关系如下图所示:

    程序被编译和链接后,num1、num1 被替换成相应的地址。使用 *num2 的话,要先通过地址 0XC100 取得变量 num2本身的值,这个值是变量 num1 的地址,然后再通过这个值取得变量num1 的数据,前后共有两次运算;而使用 num1 的话,可以通过地址 0X1000 直接取得它的数据,只需要一步运算。

    也就是说,使用指针是间接获取数据,使用变量名是直接获取数据,前者比后者的代价要高。

    指针除了可以获取内存上的数据,也可以修改内存上的数据,例如:

    int main()
    {
        int num1 = 10;
        int *num2 = &num1;
    
        *num2 = 20;
    
        printf("%d
    ", *num2);
        printf("%d
    ", num1);
    }
    

    四、再来讨论函数的参数传递

    平时在函数调用时候,一般都会传入一个普通的值,然后在函数里进行一些操作,比如传入一个整形的id,通过这个id查找对应的信息,如果我们想通过一个函数,来改变主函数的内容,就需要把地址当作参数传递,在函数里边通过地址,修改里边的内容,比如:

    void updateVal(int *num)
    {
        *num = 20;
    }
    int main()
    {
        int num1 = 10;
    
        updateVal(&num1);
    
        printf("%d
    ", num1);
    
    }
    

    主程序把变量num1的地址传递给函数updateVal,updateVal函数的参数num是一个指针,接存放变量num1的地址。在函数updateVal中,根据指针中的地址直接操作内存,从而修改了主程序中变量num1的值。

    我们已经使用scanf函数很多次了,调用scanf函数的时候,需要在变量前面加符号&,其实就是把变量的地址传给scanf函数,scanf函数根据传进去的地址直接操作内存,改变内存中的值,完成了对变量的赋值。

  • 相关阅读:
    Container(容器)
    version ctrl
    url和uri的区别
    Injector
    build tool
    变量
    python中break和continue的区别
    同步代码块以及同步方法之间的区别以及联系
    写在前面
    WebService入门
  • 原文地址:https://www.cnblogs.com/dcy521/p/14449660.html
Copyright © 2020-2023  润新知