• C语言之指针与数组总结


    和指针相关的问题口诀1

    1. 地址变量得地址,得谁地址指向谁

    和指针相关的问题要画图: 内容变量画房子,指针画箭头

    ---->口

    ----------------------------------------------------

    和指针相关的两个特殊运算符:

    一、"&" 取地址运算符,通过&运算符可以取出普通变量的地址;

    二、"*"  有两种意义:

       1.  为指针标志: 是否为指针标志主要看前面是否有类型,此处有一个int

       2.  为指针运算符:

         在等号右面为取值。*可以取出指针变量所指向的普通变量的值。

         在等号左面为赋值。*可以将指针变量所指向的普通变量的值,修改为其他。

            口诀2有* 为内容值,不是读就是写。等号左面为赋值, 其余都为取值。

       3.  为乘法运算符。当且仅当左右的都为变量时。略。

    int a, b =20, c=30, d=40, *p; (正确,此处的*为指针标志,只起到定义的左右,没有取值和赋值的作用。是否为指针标志主要看前面是否有类型,此处最前面有一个int)

    p=&d; (正确,p指向d的地址)

    a=*p;  (正确,此处的*为取值。最后结果a的值变为了d的值40)

    *p =c; (正确,此处的*为赋值。最后结果d的值变为了C的值30)

    *p =&b; (运行错误,左边为内容值,右边为地址,不等价)

    --------------------------------------------------------

    和指针相关的等价表达式

    若指针变量p指向变量a,即将变量a的地址赋给了指针变量p.

    如:int a=20, int *p=&a;

    则有如下结果:

    A、*p <=> a

    B、 p <=> &a

    C、 &*p <=> &a <=> p

    D、*&a <=> *p <=> a

    E、 (*p)++  a++ 

         (*p)--  a--    

         ++(*p)  ++a   ++*p   

          --(*p)  --a   --*p

    可以看出 * 和 & 是互逆的两个运算符

    --------------------------------------------------------

    所有的指针变量在内存中分配的字节数相同 sizeof(指针) 永远是 两个字节, 不管指针定义时是 int *, float * 还是 double * . 详细如下

    int *p1;   则 p1以后必须指向int 类型的变量。   但指针本身的长度,sizeof(p1) 为2个字节(2*8bit -16bit)

    float *p2;   则 p2以后必须指向float 类型的变量。   但指针本身的长度,sizeof(p2) 为2个字节(2*8bit -16bit)

    double *p3;   则 p3以后必须指向double 类型的变量。   但指针本身的长度,sizeof(p3) 为2个字节(2*8bit -16bit)

    -----------------------------------------------------------

    四道例题:

    例子1.

    void fun (int *x , int *y) {
      printf("%d, %d", *x, *y) ;
      *x = 3;
      *y = 4;
    }

    main()
    {
    int x = 1, y = 2
    fun(&y, &x);
    printf("%d, %d", x, y);
    }


    结果
    2, 1
    4, 3

    注意main在调用fun函数时, y 和x故意写颠倒了。

     --------------------------------------------------------------

    例子2. 

    #include <stdio.h>
    void swap(int *p1, int *p2)
    {
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
    }

    main()
    {
    int a, b;
    int * p1 = &a, *p2 = &b;
    scanf(%d %d, p1, p2);
    swap(p1, p2);
    prinf("%d, %d", *p1, *p2);
    }

    如果在控制台输入  2 和 5

    则输出结果为 

    5, 2

    原因: 在调用swap函数时使用了职称,所以在swap函数内部对p1,p2 所引用的内容值的修改,会影响外面的a和b的值。

     --------------------------------------------------------------

    例子3:

    #include <stdio.h>
    void swap(int *p1, int *p2)
    {
    int *temp;
    temp = p1;
    p1 = p2;
    p2 = temp;
    }

    main()
    {
    int a, b;
    int * p1 = &a, *p2 = &b;
    scanf(%d %d, p1, p2);
    swap(p1, p2);
    prinf("%d, %d", *p1, *p2);
    }

    和2不同, swap函数中的temp为指针,temp=p1使得temp指向了2,p1=p2使得p1指向了5,p2=temp使得p2指向了5.

    但最后的打印结果仍为
    2,5


    原因是:虽然main中调用swap函数时使用了指针传递,但swap函数中的所有操作都是:将指针本身的修改,而没有再次使用*操作符来修改“指针指向的内容值”

    口诀3:没有*的指针操作为地址,地址的赋值意味着改指向。

    ---------------------------------------------------------------------

    例子4:

    #include <stdio.h>
    void swap(int *p1, int *p2)
    {
    int *temp;
    *temp = *p1;
    *p1 = *p2;
    *p2 = *temp;
    }

    main()
    {
    int a, b;
    int * p1 = &a, *p2 = &b;
    scanf(%d %d, p1, p2);
    swap(p1, p2);
    prinf("%d, %d", *p1, *p2);
    }

    和2很像。但唯一不同是,temp定义为指针而不是普通变量。看上去似乎应该和2的输出结果一样,仍为
    2,5 。

    但实际运行时编译器会报错:非法的内存写入。

    原因是:temp为野指针,并没有预订指向哪里。如果指向系统区,则可能导致操作系统死机或崩溃。

    如果temp在定义后,马上给一个初始值,就不会有问题了。

     ---------------------------------------------------------------------

    指针、数组的等价符号

    若将数组作为形参,则将数组名作为指针变量来处理。

    int fun(int a[10]) <=> int fun(int *a) <=> int fun(int a[])

    可以看出,口诀4:  &与*互逆。 *与[]等价, &与[]互逆

    例子5:

    int s[10], a, b;
    in d[3][6];

    int *p;
    p=&a; //p 指向了整数a
    p = &s[2]; //p指向了s数组的第二个元素
    p= &d[2][4];////p指向了d数组的第二行、第四列的元素。

    所以,以上的语句都是对的。

    上面的例子:

    1. 定义了一个int s[10];   则 s等同于 &s[0].   即,看到一个数组,就马上联想到他代表的是数组第一个元素的地址。

        在C语言中规定,数据名代表数组的首地址,并且是一个地址常量

    2. 另外,如果定义了一个指针 int *ppp = s;  则   ppp 定价于s,  同时等价于 &s[0]。

     ---------------------------------------------------------------------

    指针的加减:


    当指针变量指向数组中的某一个地址时,指针变量加1后指向数组的下一个元素,
    指针变量减1时指向数组的前一个元素。

     例子6:

    float a[10]; float *p;
    p=&a[4]; 则p-3指向?

    先画图:

    a[0] | a[1] | a[2] | a[3] | a[4] | ...

    p的初始位置指向了 a[4],  则 p-3 为向前3个,指向了 a[1]

     口诀5:  指针的加减是向前或向后移动了n个元素

     ---------------------------------------------------------------------

    int a[N], *p=a;

    则有:

    地址三等价:

    存在等价表达式:

    p+i <=> a+i <=> &a[i]  代表的是第i个元素的地址

    元素四等价:

    存在等价表达式:

    1.   *(p+i) <=> *(a+i) <=> a[i]   代表的是第i个元素的值

    2.  另外,还有 p[i] <=> a[i] 。 p[i] 的用法不多见,但无任何错误,代表的也是第i个元素的值。原因是p和a完全等价。

    整理出来的等价式如下:

    a) *(p+i) <=> *(a+i) <=> a[i] <=> p[i]
    b) p++ <=> ++p <=>  p+=1 <=>  p=p+1
    c) p-- <=>  --p  <=>  p-=1  <=>  p=p-1
    d) *p++  <=>   *(p++)
       说明:* 与 ++ 的运算优先级一样,所以按照从右到左的结合原则,先执行++,后执行*
       ++在p的后面,为执行后再加。即先把p的值取出,指针再加1.
    e) *++p  <=>  *(++p)
        ++在p的前面,为先加再执行。即先把指针加1, 再把移动后的p所指向的值取出,
    f) (*p)++ <=>   ++(*p)  <=>   ++*p
        将p的内容自增
    g) (*p)--  <=>  --(*p)  <=>   --*p
        将p的内容自减

  • 相关阅读:
    jQuery插件开发入门
    [转]JS学习总结-技巧、方法、细节
    JS无法获取display为none的隐藏元素的宽度和高度的解决方案
    vuejs2.0运用原生js实现简单的拖拽元素功能
    HTML5效果:Canvas 实现圆形进度条并显示数字百分比
    git常用命令总结以及用github来展示你的前端页面
    jQuery 对AMD的支持(Require.js中如何使用jQuery)
    vue+springboot上传和下载附件功能
    springboot+vue实现文件上传
    Spring boot+Vue全栈开发---Spring Boot文件上传
  • 原文地址:https://www.cnblogs.com/kungfupanda/p/3748064.html
Copyright © 2020-2023  润新知