指针

指针与指针类型

  • 指针

    • 概念:在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值指向(points to)存在电脑存储器中的另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元(一个内存单元大小为一个字节)

      注:

      • 32位机器上,指针变量大小为4byte(4x8=32);64位机器上,指针变量大小为8byte
      • 32位机器上:由于2^(32-10-10-10) = 4GB,故内存最大为4G
    • 常量指针

      表示指向常量的指针,例如

      const int* ptr1 = &a;
    • 指针常量

      表示指针是一个常量,指针指向不允许改变,例如

      int* const ptr2 = &b;
  • 指针类型

    • 概念:

      Q:为什么指针大小在同一个平台上大小都相同,为什么还要区分指针类型?

      A:存放时,虽然各个指针类型结果一样,但是解引用后,结果不一样!例如: char*、int*、float* 等

    • 理解:

      • 指针类型决定了指针解引用操作时,能访问的大小

        注:访问大小为指向的类型的大小,下面同理

      • 指针类型决定了指针+1、-1时,到底加减几个字节


野指针、指针运算

  • 野指针

    • 概念:指针指向的位置是不可知的指针为野指针

    • 野指针形成原因

      • 指针未初始化(没有初始化为NULL)

      • 指针越界访问

      • 指针指向的内存空间被释放

      注:在动态内存开辟处,详细讲解堆区内存被释放的情况

    • 如何避免野指针

      • 指针初始化(初始化为空指针NULL)
      • 小心指针越界
      • 指针指向空间释放,及时把指针置为NULL
      • 指针使用前检查有效性。即闲时置为空指针,用时判断是否为空指针

      注:NULL在编译器中的定义:#define NULL((void*)0)

  • 指针运算

    • 指针加减整数

      int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
      int* p = arr;
      for (int i = 0; i < 5; i++) {
          printf("%d\n", *p);
          p += 2;
      }

      加减后,指针指向的地址位置,移动到距离指针类型访问空间大小整数倍的地址位置

    • 指针减指针

      int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
      printf("%d\n", &arr[9] - &arr[0]);
      // 输出结果:9

      指针减指针表示到起始地址中间的内存长度

      注:

      • 小地址-大地址结果为负数
      • 两个指针必须指向同一块空间(如数组空间),才有意义
    • 指针类型对指针减指针的影响

      int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
      char* p1 = &arr[9];
      char* p2 = arr;
      printf("%d\n", p1 - p2);
      // 输出结果:36
    • 指针的关系运算

      float values[5];
      float* p;
      for (p = values; p < &values[5];) {
          *p++ = 0;
      }

      注:

      • &values[5]指的是数组末尾的野指针
      • 标准规定:
        1. 允许数组元素指针与最后一个元素后的内存位置进行指针比较
        2. 不允许与首元素之前的内存位置进行比较

字符指针

  • 字符指针的一般使用

    char ch = 'a';
    char* pch = &ch;
    *pch = 'b';
  • 常量字符串在字符指针中的使用

    const char* pstr = "666";

    注:

    • 本质是把常量字符串”666”的首字符地址放入到pstr中3
    • 常量字符串的内容不允许被更改!(报错:写入访问权限冲突)
  • 常量字符串的细节

    char str1[] = "hello bit.";
    char str2[] = "hello bit.";
    const char* str3 = "hello bit.";
    const char* str4 = "hello bit.";
    if (str1 == str2)
        printf("str1 and str2 are same\n");
    else
        printf("str1 and str2 are not same\n");
    
    if (str3 == str4)
        printf("str3 and str4 are same\n");
    else
        printf("str3 and str4 are not same\n");

    输出结果:

    str1 and str2 are not same
    str3 and str4 are same

    由此可得:

    • 当用同一个常量字符串去初始化不同的数组时,会开辟出不同的内存块
    • 当两个指针指向同一个常量字符串时,它们实际会指向同一个地址

    注:C/C++会把常量字符串储存在单独的一个内存区域。当几个指针指向同一个常量字符串时,他们实际会指向同一个地址

« 变量存储 ← 返回列表 指针进阶 »