C 语言 指针(Pointer)
                           
天天向上
发布: 2025-04-01 23:21:31

原创
651 人浏览过

C 语言中的 指针(Pointer)是其最强大的特性之一,它允许程序直接操作内存,提高代码的效率和灵活性。指针广泛用于动态内存分配、数据结构(如链表、树)、数组操作、函数参数传递等。本文将从基础到高级全面解析 C 指针,包括底层原理、使用技巧和注意事项。


1. 指针的基本概念

在 C 语言中,指针是一个 变量,它存储 另一个变量的内存地址。指针本身也占用内存(通常为 4 或 8 字节,取决于系统架构)。

1.1 指针的定义

int a = 10;
int *p = &a;  // p 存储变量 a 的地址
  • *p 表示 指针解引用(dereferencing),即访问指针指向的值。
  • &aa 的地址。

1.2 指针的基本操作

#include <stdio.h>

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

    printf("变量 a 的值: %d\n", a);
    printf("变量 a 的地址: %p\n", &a);
    printf("指针 p 存储的地址: %p\n", p);
    printf("指针 p 指向的值: %d\n", *p);

    return 0;
}

示例输出

变量 a 的值: 10
变量 a 的地址: 0x7ffee1b56c44
指针 p 存储的地址: 0x7ffee1b56c44
指针 p 指向的值: 10

2. 指针的类型

指针的类型决定了解引用(*)时读取数据的方式。例如:

int *p1;   // 指向 int 类型
char *p2;  // 指向 char 类型
double *p3; // 指向 double 类型

注意: 指针本身的大小通常是固定的(32 位系统 4 字节,64 位系统 8 字节),但指向的数据类型不同。


3. 指针运算

3.1 指针加减

指针可以执行加法和减法运算:

int arr[] = {10, 20, 30, 40};
int *p = arr; // 指向数组首元素

printf("%d\n", *(p + 1)); // 访问 arr[1] (20)
printf("%d\n", *(p + 2)); // 访问 arr[2] (30)

原理
指针 p 增加 1,表示前进 sizeof(int)(4 字节)。

3.2 指针的比较

if (p1 == p2) {
    printf("两个指针指向相同地址\n");
}

3.3 指针的自增、自减

p++; // 移动到下一个元素
p--; // 移动到上一个元素

4. 指针与数组

4.1 一维数组与指针

int arr[] = {1, 2, 3, 4};
int *p = arr;

printf("%d\n", p[2]); // 等价于 arr[2],输出 3

arr[i] 等价于 *(arr + i)

4.2 二维数组与指针

int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = matrix; // 指向包含 3 个元素的数组
printf("%d\n", p[1][2]); // 访问 matrix[1][2],输出 6

5. 指针与函数

5.1 作为函数参数

指针可以用于函数参数,以便 修改原始数据

void modify(int *p) {
    *p = 20; // 修改原始值
}

int main() {
    int a = 10;
    modify(&a);
    printf("%d\n", a); // 输出 20
    return 0;
}

5.2 返回指针

int* getPointer() {
    static int x = 100;
    return &x;
}

⚠️ 注意:不要返回局部变量的地址,否则会导致未定义行为。


6. 指针与 malloc() 动态内存分配

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

int main() {
    int *p = (int*) malloc(5 * sizeof(int)); // 分配 5 个 int 空间
    if (p == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    for (int i = 0; i < 5; i++) {
        p[i] = i * 10;
        printf("%d ", p[i]);
    }

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

⚠️ 注意

  • 分配后必须释放 free(p),否则可能会造成 内存泄漏

7. 指针数组 & 指针指针

7.1 指针数组

int a = 1, b = 2, c = 3;
int *arr[] = {&a, &b, &c};

printf("%d\n", *arr[1]); // 输出 2

指针数组 arr[] 里存储了 a, b, c 的地址。

7.2 二级指针(指向指针的指针)

int x = 10;
int *p = &x;
int **pp = &p;

printf("%d\n", **pp); // 输出 10

8. void * 指针

void * 指针可以指向任何类型:

void *ptr;
int a = 10;
ptr = &a;
printf("%d\n", *(int*)ptr);

9. 指针的常见错误

9.1 悬空指针(Dangling Pointer)

int *p;
{
    int x = 10;
    p = &x;
} // x 被销毁,p 成为悬空指针

解决方案: 避免返回局部变量地址,或者在 free() 后将指针置 NULL

9.2 野指针(Uninitialized Pointer)

int *p; // p 未初始化,可能指向垃圾地址

解决方案: 在声明指针时初始化:

int *p = NULL;

10. 总结

指针特性说明
存储地址指针存储变量的地址,而非变量本身
* 解引用访问指针指向的数据
& 取地址获取变量地址
指针运算支持 +, -, ++, --
malloc/free动态内存分配
void *通用指针,指向任意类型

11. 参考资料

发表回复 0

Your email address will not be published. Required fields are marked *