Skip to content

1. 指针基础补充

1.1 指针的大小

  • 指针的大小
    • 无论什么类型的指针,在同一平台上的大小总是固定的。
    • 在 32 位平台上,所有的指针(地址)都是 32 位(4 字节)。
    • 在 64 位平台上,所有的指针(地址)都是 64 位(8 字节)。
  • 示例
    c
    #include <stdio.h>
    
    int main() {
        char b = 'b';
        int *a = NULL;
        char *b_ptr = &b;
        float *c = NULL;
    
        printf("sizeof(a) = %zu\n", sizeof(a)); // 输出 8 (在 64 位平台上)
        printf("sizeof(b_ptr) = %zu\n", sizeof(b_ptr)); // 输出 8 (在 64 位平台上)
        printf("sizeof(c) = %zu\n", sizeof(c)); // 输出 8 (在 64 位平台上)
    
        return 0;
    }

1.2 const 修饰的指针变量

  • 常量指针
    • 声明指针变量时可以使用 const 关键字来修饰指针所指向的内容。
    • const 可以放在不同的位置,表示不同的含义:
      • const 放在类型名称前:指针所指向的内容不可修改。
      • const 放在指针符号前:指针本身不可修改。
  • 示例
    c
    #include <stdio.h>
    
    int main() {
        const int a = 10; // 常量
        int b = 20; // 变量
    
        // 常量指针:指针所指向的内容不可修改
        const int *p1 = &a;
        // p1 = &b; // 错误:不能将非常量的地址赋给常量指针
        // *p1 = 30; // 错误:不能通过常量指针修改内容
    
        // 指针常量:指针本身不可修改
        int *const p2 = &b;
        // p2 = &a; // 错误:不能改变指针常量的指向
        *p2 = 30; // 正确:可以通过指针常量修改内容
    
        // 常量指针常量:指针和指针所指向的内容都不可修改
        const int *const p3 = &a;
        // p3 = &b; // 错误:不能改变指针常量的指向
        // *p3 = 30; // 错误:不能通过常量指针修改内容
    
        return 0;
    }

2. 指针和数组

2.1 数组名

  • 数组名字是数组的首元素地址
    • 数组名本质上是一个指向数组第一个元素的指针。
  • 数组元素指针
    • 一个变量有地址,一个数组包含若干元素,每个数组元素也有相应的地址。
    • 指针变量也可以保存数组元素的地址,只要一个指针变量保存了数组元素的地址,我们就称之为数组元素指针。
  • 示例
    c
    #include <stdio.h>
    
    int main() {
        int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        printf("a = %p\n", (void *)a); // 输出数组首地址
        printf("&a[0] = %p\n", (void *)&a[0]); // 输出数组首地址
    
        return 0;
    }

2.2 数组名不能参与加减计算

  • 数组名的限制
    • 数组名是一个常量指针,它不能参与加减运算。
    • 例如,a + 1 是非法的,但 &a[0] + 1 是合法的。
  • 示例
    c
    #include <stdio.h>
    
    int main() {
        int a[] = {1, 2, 3, 4, 5, 6, 7};
        char c[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    
        int *pa = a;
        char *pc = c;
    
        printf("pa = %p\n", (void *)pa);
        printf("pc = %p\n", (void *)pc);
        printf("\n");
    
        pa++;
        pc++;
        // a++; // 错误:数组名不能参与加减运算
        // c++; // 错误:数组名不能参与加减运算
    
        printf("pa = %p\n", (void *)pa);
        printf("pc = %p\n", (void *)pc);
        printf("\n");
    
        pa += 2;
        pc += 2;
        // a += 2; // 错误:数组名不能参与加减运算
        // c += 2; // 错误:数组名不能参与加减运算
    
        printf("pa = %p\n", (void *)pa);
        printf("pc = %p\n", (void *)pc);
        printf("\n");
    
        printf("*(pa + 1) = %d\n", *(pa + 1)); // 输出 5
        printf("*pa = %d\n", *pa);             // 输出 4
        printf("*(pa - 1) = %d\n", *(pa - 1)); // 输出 3
        printf("\n");
    
        printf("*(pc + 1) = %c\n", *(pc + 1)); // 输出 e
        printf("*pc = %c\n", *pc);             // 输出 d
        printf("*(pc - 1) = %c\n", *(pc - 1)); // 输出 c
    
        return 0;
    }

2.3 通过指针遍历数组

  • 遍历数组
    • 使用指针遍历数组是一种常见的方法,可以方便地访问和修改数组元素。
  • 示例
    c
    #include <stdio.h>
    
    int main() {
        int a[] = {1, 2, 3, 4, 5, 6, 7};
        char c[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
    
        int *pa = a;
        char *pc = c;
    
        printf("pa = %p\n", (void *)pa);
        printf("pc = %p\n", (void *)pc);
        printf("\n");
    
        pa++;
        pc++;
        // a++; // 错误:数组名不能参与加减运算
        // c++; // 错误:数组名不能参与加减运算
    
        printf("pa = %p\n", (void *)pa);
        printf("pc = %p\n", (void *)pc);
        printf("\n");
    
        pa += 2;
        pc += 2;
        // a += 2; // 错误:数组名不能参与加减运算
        // c += 2; // 错误:数组名不能参与加减运算
    
        printf("pa = %p\n", (void *)pa);
        printf("pc = %p\n", (void *)pc);
        printf("\n");
    
        printf("*(pa + 1) = %d\n", *(pa + 1)); // 输出 5
        printf("*pa = %d\n", *pa);             // 输出 4
        printf("*(pa - 1) = %d\n", *(pa - 1)); // 输出 3
        printf("\n");
    
        printf("*(pc + 1) = %c\n", *(pc + 1)); // 输出 e
        printf("*pc = %c\n", *pc);             // 输出 d
        printf("*(pc - 1) = %c\n", *(pc - 1)); // 输出 c
    
        return 0;
    }

总结

  1. 指针基础补充
    • 指针的大小:在 32 位平台上为 4 字节,在 64 位平台上为 8 字节。
    • const 修饰的指针变量:常量指针、指针常量和常量指针常量的不同用法。
  2. 指针和数组
    • 数组名:数组名是数组的首元素地址。
    • 数组元素指针:指针变量可以保存数组元素的地址。
    • 数组名不能参与加减计算:数组名是一个常量指针,不能参与加减运算。
    • 通过指针遍历数组:使用指针遍历数组是一种常见且有效的方法。

知识如风,常伴吾身