跳到主要内容
🔍

代码示例:1.3.1 指针基础与 const 指针

全部示例均标注编译命令、适用环境与实测状态;完整验证记录见《03.5-代码编译运行验证记录》。

  • examples/ex1-pointer-basics.c · 地址、解引用与传址交换

    /* ex1-pointer-basics.c —— 指针基础:地址、解引用与传址交换
     * 适用环境:Linux / Windows(MinGW) 标准:C11
     * 编译:gcc ex1-pointer-basics.c -o ex1 -std=c11 -Wall -Wextra -Wpedantic
     */
    #include <stdio.h>
     
    /* 传值交换:函数内交换的是形参副本,main 中的变量不变(演示用) */
    static void swap_by_value(int a, int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
        printf("swap_by_value 内部:a=%d, b=%d\n", a, b);
    }
     
    /* 传址交换:通过指针直接修改 main 中的变量 */
    static void swap_by_address(int *pa, int *pb)
    {
        if (pa == NULL || pb == NULL) {          /* 使用前判空,杜绝野指针 */
            fprintf(stderr, "swap_by_address: 收到空指针\n");
            return;
        }
        int tmp = *pa;
        *pa = *pb;
        *pb = tmp;
    }
     
    int main(void)
    {
        int x = 10;
        int y = 20;
        int *px = &x;                            /* px 保存 x 的地址 */
     
        printf("x 的值 = %d,x 的地址 = %p\n", x, (void *)&x);
        printf("px 保存的地址 = %p,*px 解引用 = %d\n", (void *)px, *px);
        printf("本平台 sizeof(int*) = %zu 字节\n", sizeof(px));   /* 64 位为 8,32 位为 4 */
     
        swap_by_value(x, y);
        printf("传值交换后:x=%d, y=%d(main 中未交换)\n", x, y);
     
        swap_by_address(&x, &y);
        printf("传址交换后:x=%d, y=%d(main 中已交换)\n", x, y);
        return 0;
    }
     
  • examples/ex2-const-pointers.c · const 指针三种写法

    /* ex2-const-pointers.c —— const 指针三种写法的可改/不可改矩阵
     * 适用环境:Linux / Windows(MinGW) 标准:C11
     * 编译:gcc ex2-const-pointers.c -o ex2 -std=c11 -Wall -Wextra -Wpedantic
     * 练习:把三处注释掉的"非法"行逐一取消注释并重新编译,观察并解释报错。
     */
    #include <stdio.h>
     
    int main(void)
    {
        int a = 1;
        int b = 2;
     
        /* ① 常量指针:指向的数据不可改,指针本身可改(const 在 * 左侧) */
        const int *p1 = &a;
        printf("p1 -> %d\n", *p1);
        p1 = &b;                 /* 合法:重新指向 b */
        /* *p1 = 10;            非法:error: assignment of read-only location '*p1' */
        printf("p1 重新指向后 -> %d\n", *p1);
     
        /* ② 指针常量:指针本身不可改,指向的数据可改(const 在 * 右侧) */
        int *const p2 = &a;
        *p2 = 11;                /* 合法:修改 a 的值 */
        /* p2 = &b;             非法:error: assignment of read-only variable 'p2' */
        printf("经 p2 修改后 a = %d\n", a);
     
        /* ③ 常量指针常量:都不可改(两侧都有 const) */
        const int *const p3 = &a;
        printf("p3 -> %d\n", *p3);
        /* *p3 = 12;            非法:error: assignment of read-only location '*(const int *)p3' */
        /* p3 = &b;             非法:error: assignment of read-only variable 'p3' */
     
        return 0;
    }
     
  • examples/ex3-null-checks.c · 空指针检查与 free 后置 NULL

    /* ex3-null-checks.c —— 空指针检查与 free 后置 NULL 的好习惯
     * 适用环境:Linux / Windows(MinGW) 标准:C11
     * 编译:gcc ex3-null-checks.c -o ex3 -std=c11 -Wall -Wextra -Wpedantic
     * 背景:本章【纠错】指出——对野指针解引用是未定义行为,任何情况下都不应尝试。
     *       本程序演示正确的防野指针习惯,而不是演示崩溃。
     */
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(void)
    {
        int *p = NULL;               /* 习惯 1:定义即初始化,杜绝野指针 */
     
        if (p != NULL) {             /* 习惯 2:使用前判空 */
            printf("%d\n", *p);
        } else {
            printf("p 是空指针,跳过解引用\n");
        }
     
        p = (int *)malloc(sizeof(int));
        if (p == NULL) {             /* 习惯 3:malloc 返回值必须检查 */
            fprintf(stderr, "malloc 失败\n");
            return 1;
        }
        *p = 42;
        printf("*p = %d\n", *p);
     
        free(p);
        p = NULL;                    /* 习惯 4:free 后置 NULL,避免悬挂指针/重复 free */
     
        if (p != NULL) {             /* 防御性检查:此处不会执行 */
            free(p);
        }
        return 0;
    }