C语言指针用法

1611 分钟阅读
C语言

1. 指针基本声明与初始化

#include <stdio.h>

int main() {
    int var = 42;
    int *ptr;       // 声明一个指向int的指针
    ptr = &var;     // 将var的地址赋给ptr

    printf("var的值: %d\n", var);
    printf("var的地址: %p\n", &var);
    printf("ptr存储的地址: %p\n", ptr);
    printf("ptr指向的值: %d\n", *ptr);  // 解引用

    return 0;
}

2. 通过指针修改变量的值

#include <stdio.h>

int main() {
    int num = 10;
    int *p = &num;

    printf("修改前: %d\n", num);
    *p = 20;   // 通过指针修改num的值
    printf("修改后: %d\n", num);

    return 0;
}

3. 指针算术运算

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int *ptr = arr;   // 指向数组首元素

    for (int i = 0; i < 5; i++) {
        printf("*(ptr+%d) = %d\n", i, *(ptr + i));
    }

    // 指针移动
    ptr += 2;
    printf("移动后ptr指向的值: %d\n", *ptr); // 30

    return 0;
}

4. 指针与数组(数组名即指针)

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *p = arr;   // 等价于 &arr[0]

    // 使用下标访问
    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d, p[%d] = %d\n", i, arr[i], i, p[i]);
    }

    // 使用指针遍历
    for (int *q = arr; q < arr + 5; q++) {
        printf("%d ", *q);
    }
    printf("\n");

    return 0;
}

5. 指针与字符串(字符指针)

#include <stdio.h>

int main() {
    char str[] = "Hello";   // 字符数组,可修改
    char *ptr = "World";    // 字符串常量,不可修改(建议加const)

    printf("str: %s\n", str);
    printf("ptr: %s\n", ptr);

    // 修改数组字符串
    str[0] = 'h';
    printf("修改后str: %s\n", str);

    // ptr指向的内容是常量,不能 *ptr = 'w';但可以指向别的字符串
    ptr = "C语言";
    printf("ptr重新指向: %s\n", ptr);

    return 0;
}

6. 指针作为函数参数(传址调用)

#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    printf("交换前: x=%d, y=%d\n", x, y);
    swap(&x, &y);
    printf("交换后: x=%d, y=%d\n", x, y);
    return 0;
}

7. 函数返回指针

#include <stdio.h>
#include <stdlib.h>

int* createArray(int size) {
    int *arr = (int*)malloc(size * sizeof(int));
    for (int i = 0; i < size; i++) {
        arr[i] = i + 1;
    }
    return arr;  // 返回动态分配的内存地址
}

int main() {
    int n = 5;
    int *myArray = createArray(n);
    for (int i = 0; i < n; i++) {
        printf("%d ", myArray[i]);
    }
    printf("\n");
    free(myArray);  // 记得释放内存
    return 0;
}

8. 指针与结构体

#include <stdio.h>
#include <string.h>

struct Student {
    int id;
    char name[20];
};

int main() {
    struct Student stu = {1001, "张三"};
    struct Student *pStu = &stu;

    // 使用指针访问成员(->运算符)
    printf("学号: %d, 姓名: %s\n", pStu->id, pStu->name);

    // 修改成员
    pStu->id = 1002;
    strcpy(pStu->name, "李四");
    printf("修改后: 学号: %d, 姓名: %s\n", stu.id, stu.name);

    return 0;
}

9. 多级指针(二级指针)

#include <stdio.h>

int main() {
    int a = 100;
    int *p = &a;    // 一级指针
    int **pp = &p;  // 二级指针

    printf("a = %d\n", a);
    printf("*p = %d\n", *p);
    printf("**pp = %d\n", **pp);

    // 通过二级指针修改a的值
    **pp = 200;
    printf("修改后 a = %d\n", a);

    return 0;
}

10. 指针数组(数组元素为指针)

#include <stdio.h>

int main() {
    int a = 10, b = 20, c = 30;
    int *arr[3];   // 指针数组,存放三个int指针
    arr[0] = &a;
    arr[1] = &b;
    arr[2] = &c;

    for (int i = 0; i < 3; i++) {
        printf("arr[%d] 指向的值: %d\n", i, *arr[i]);
    }

    // 字符串指针数组
    char *fruits[] = {"Apple", "Banana", "Cherry"};
    for (int i = 0; i < 3; i++) {
        printf("%s\n", fruits[i]);
    }

    return 0;
}

11. 函数指针(指向函数的指针)

#include <stdio.h>

int add(int x, int y) {
    return x + y;
}

int subtract(int x, int y) {
    return x - y;
}

int main() {
    int (*funcPtr)(int, int);  // 声明函数指针

    funcPtr = &add;            // 指向add函数
    printf("add(3,5)=%d\n", funcPtr(3, 5));

    funcPtr = subtract;        // 函数名即地址,可不加&
    printf("subtract(8,3)=%d\n", funcPtr(8, 3));

    return 0;
}

12. 动态内存分配(malloc/free)

#include <stdio.h>
#include <stdlib.h>

int main() {
    int n;
    printf("请输入元素个数: ");
    scanf("%d", &n);

    int *arr = (int*)malloc(n * sizeof(int));
    if (arr == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        arr[i] = i * 10;
    }

    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr);  // 释放内存
    return 0;
}

13. 空指针与野指针

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr1 = NULL;    // 空指针,不指向任何有效内存
    int *ptr2;           // 野指针(未初始化),危险!

    // 对空指针解引用会导致运行时错误(段错误)
    // printf("%d", *ptr1); // 禁止这样写

    // 避免野指针:初始化或赋值为NULL
    ptr2 = (int*)malloc(sizeof(int));
    if (ptr2 != NULL) {
        *ptr2 = 123;
        printf("*ptr2 = %d\n", *ptr2);
        free(ptr2);
    }
    ptr2 = NULL; // 释放后置NULL,避免悬空指针

    return 0;
}

14. const 与指针(指向常量的指针 / 常量指针)

#include <stdio.h>

int main() {
    int a = 10, b = 20;

    // 指向常量的指针:不能通过指针修改所指向的值,但指针本身可以指向别的变量
    const int *p1 = &a;
    // *p1 = 15;  // 错误
    p1 = &b;       // 合法

    // 常量指针:指针本身是常量,不能再指向别的地址,但可以修改指向的值
    int *const p2 = &a;
    *p2 = 15;      // 合法
    // p2 = &b;    // 错误

    // 指向常量的常量指针:都不可修改
    const int *const p3 = &a;
    // *p3 = 15;   // 错误
    // p3 = &b;    // 错误

    printf("a = %d, b = %d\n", a, b);
    return 0;
}