• 19 数组、指针


    1 指针的本质分析

    1.1 问题

    • 程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间?

      • 不是,还可以利用指向这段内存空间的指针

        int i = 5;
        int* p = &i;
        
        printf("%d, %p
        ",i,p);  // 5, 0xbf847b5c
        
        *p = 10;
        
        printf("%d, %p
        ",i,p);  // 10, 0xbf847b5c
        

    1.2 传值调用与传址调用

    • 指针是变量,因此可以声明指针参数

    • 当一个函数体内部需要改变实参的值,则需要使用指针参数

    • 函数调用时实参值将复制到形参

    • 指针适用于复杂数据类型作为参数的函数中

    • 示例:利用指针交换变量

      #include <stdio.h>
      
      int swap(int* a, int* b)
      {
          int c = *a;
          
          *a = *b;
          
          *b = c;
      }
      
      int main()
      {
          int aa = 1;
          int bb = 2;
          
          printf("aa = %d, bb = %d
      ", aa, bb);  // aa = 1, bb = 2
      
          swap(&aa, &bb);
          
          printf("aa = %d, bb = %d
      ", aa, bb);  // aa = 2, bb = 1
          
          return 0;
      }
      

    1.3 常量与指针

    • 常量与指针的组合

      • const int* p;p 可变,p 指向的内容不可变 => 指向常量的指针(pointer to const)
      • int const* p;p 可变,p 指向的内容不可变
      • int* const p;p 不可变,p 指向的内容可变 => 常量指针(const pointer)
      • const int* const p;pp 指向的内容都不可变
    • 规则:左数右指

      • const 出现在 * 号左边时,指针指向的数据为常量
      • const 出现在 * 号右边时,指针本身为常量
    • 示例:常量与指针

      • Demo

        #include <stdio.h>
        
        int main()
        {
            int i = 0;
            
            const int* p1 = &i;
            int const* p2 = &i;
            int* const p3 = &i;
            const int* const p4 = &i;
            
            *p1 = 1;    // compile error
            p1 = NULL;  // ok
            
            *p2 = 2;    // compile error
            p2 = NULL;  // ok
            
            *p3 = 3;    // ok
            p3 = NULL;  // compile error
            
            *p4 = 4;    // compile error
            p4 = NULL;  // compile error
            
            return 0;
        }
        
      • 编译

        test.c: In function ‘main’:
        test.c:12: error: assignment of read-only location ‘*p1’
        test.c:15: error: assignment of read-only location ‘*p2’
        test.c:19: error: assignment of read-only variable ‘p3’
        test.c:21: error: assignment of read-only location ‘*p4’
        test.c:22: error: assignment of read-only variable ‘p4’
        

    2 数组的本质分析

    2.1 数组地址与数组名

    • 数组名代表数组首元素的地址

    • 数组的地址需要用取地址符 &才能得到

    • 数组首元素的地址值数组的地址值相同

    • 数组首元素的地址与数组的地址是不同的概念

    • 示例:数组名与数值地址

      #include <stdio.h>
      
      int main()
      {
          int a[5] = { 0 };
      
          printf("a = %p
      ", a);  // 数组首元素地址: a = 0xbfeb1ffc
          printf("&a = %p
      ", &a);  // 数组地址: &a = 0xbfeb1ffc
          printf("&a[0] = %p
      ", &a[0]);  // 数组首元素地址: &a[0] = 0xbfeb1ffc
          
          return 0;
      }
      

    2.2 数组名

    • 数组名在大多数情况下可以看作是一个指向数组第一元素的常量指针(T* const):const pointer

    • 数组名“指向“的是内存中数组首元素的起始位置

    • 数组名不包含数组的长度信息

    • 在表达式中数组名只能作为右值使用

    • 只有在下列场合中数组名不能看作常量指针

      • 数组名作为 sizeof 操作符的参数
      • 数组名作为 & 操作符的参数
    • 数组名不是指针,不能将其等同于指针

    • 示例:数组和指针并不相同

      #include <stdio.h>
      
      int main()
      {
          int a[5] = {0};
          int b[2];
          int* p = NULL;
          
          p = a;
          
          printf("a = %p
      ", a);  // a = 0xbfa2b680
          printf("p = %p
      ", p);  // p = 0xbfa2b680
          printf("&p = %p
      ", &p);  // &p = 0xbfa2b69c
          printf("sizeof(a) = %d
      ", sizeof(a));  // 20
          printf("sizeof(p) = %d
      ", sizeof(p));  // 4
         
          printf("
      ");
      
          p = b;
          
          printf("b = %p
      ", b);
          printf("p = %p
      ", p);
          printf("&p = %p
      ", &p);
          printf("sizeof(b) = %d
      ", sizeof(b));
          printf("sizeof(p) = %d
      ", sizeof(p));
          
          b = a;
        
          return 0;
      }
      
      
  • 相关阅读:
    岛田庄司《占星术杀人魔法》读后感
    OutputCache祥解
    ZOJ Monthly, June 2014 月赛BCDEFGH题题解
    接口和抽象类有什么差别
    C语言指针的初始化和赋值
    深入探讨this指针
    郁 繁体为“鬰” 古同 “鬱”
    socketpair的使用
    Android的FrameLayout使用要注意的问题
    下确界和上确界
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13646532.html
Copyright © 2020-2023  润新知