c语言指针

一、指针的基本概念

指针本质上是一种变量,其存储的数值是内存地址。通过指针,能够对该内存地址里存储的数据进行间接访问。

int num = 42;     // 定义一个整型变量
int *ptr;         // 定义一个指向整型的指针
ptr = #       // 将num的地址赋给ptr
printf("%p\n", ptr);  // 输出ptr存储的地址
printf("%d\n", *ptr); // 解引用,输出42

二、指针的声明与初始化

指针在声明时,需要明确其指向数据的类型,并且要借助取地址运算符&来进行初始化。

int a = 10;
int *p = &a;      // 正确:初始化指针p
int *q;           // 未初始化的指针(野指针)
q = &a;           // 正确:后续赋值

三、指针的解引用

运用解引用运算符*,可以获取指针所指向内存地址中的值。

int x = 20;
int *px = &x;
*px = 50;         // 修改x的值为50
printf("%d\n", x); // 输出50

四、指针运算

指针支持的运算操作包括递增++、递减--以及加减法。

int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;   // 指向数组首元素
ptr++;            // 指向下一个元素(地址+4字节)
printf("%d\n", *ptr); // 输出2

五、指针与数组

在 C 语言中,数组名可被看作是指向数组首元素的常量指针。

int arr[3] = {10, 20, 30};
printf("%d\n", *arr);     // 输出10
printf("%d\n", arr[1]);   // 等价于*(arr + 1)

六、指针与函数

借助指针作为函数参数,能够实现对实参的修改,也就是所谓的 "传址调用"。

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

int main() {
    int x = 5, y = 10;
    swap(&x, &y);        // 交换x和y的值
    printf("%d %d\n", x, y); // 输出10 5
    return 0;
}

七、多级指针

多级指针指的是指针的指针,通过它可以间接访问更深层次的数据。

int num = 100;
int *p = #
int **pp = &p;          // 二级指针
printf("%d\n", **pp);   // 输出100

八、动态内存分配

在 C 语言中,可以利用malloccallocreallocfree函数来对堆内存进行管理。

int *ptr = (int *)malloc(sizeof(int)); // 分配4字节内存
if (ptr != NULL) {
    *ptr = 200;
    free(ptr);       // 释放内存,防止内存泄漏
}

九、指针与字符串

字符串常量实际上是指向字符数组的指针。

char *str = "Hello";  // 指向字符串常量的指针
printf("%c\n", *str); // 输出'H'
printf("%s\n", str);  // 输出"Hello"

十、函数指针

函数指针能够存储函数的地址,进而实现函数的动态调用。

int add(int a, int b) { return a + b; }
int (*func_ptr)(int, int) = add; // 函数指针
printf("%d\n", func_ptr(3, 4));  // 输出7

十一、指针数组(Array of Pointers)

指针数组属于数组,它的每个元素都是指针。其定义格式为:type *array_name[size];

int a = 10, b = 20, c = 30;
int *ptr_arr[3] = {&a, &b, &c}; // 指针数组
printf("%d\n", *ptr_arr[0]);    // 输出10

典型应用场景

处理字符串数组:

char *fruits[3] = {"Apple", "Banana", "Cherry"};
printf("%s\n", fruits[1]);      // 输出"Banana"
int *arr[5];
for(int i=0; i<5; i++) {
    arr[i] = (int *)malloc(sizeof(int));
    *arr[i] = i*10;
}

十二、数组指针(Pointer to an Array)

数组指针是一种指针,它指向的是整个数组。其定义格式为:type (*pointer_name)[size];

int arr[5] = {1,2,3,4,5};
int (*ptr)[5] = &arr;  // 数组指针
printf("%d\n", (*ptr)[2]); // 输出3

关键要点

  • 数组指针的步长为整个数组的大小:
printf("%p\n", ptr);     // 数组首地址
printf("%p\n", ptr+1);   // 地址+20字节(假设int占4字节)
  • 二维数组和数组指针:
int matrix[3][4];
int (*ptr)[4] = matrix;  // 指向包含4个int的数组
ptr++;                   // 指向下一行

十三、指针数组 vs 数组指针

特征指针数组数组指针
本质数组指针
定义int *arr[5];int (*ptr)[5];
元素类型指针整个数组
用途存储多个指针指向多维数组
地址运算元素地址间隔为指针大小地址间隔为整个数组大小

十四、复杂声明解析(使用右左法则)

int *(*arr[5])(int); // 声明一个包含5个元素的数组
                      // 每个元素是指向函数的指针
                      // 该函数接受int参数并返回int*

解析步骤

  1. arr[5]结合 → arr是数组
  2. *arr[5] → 数组元素是指针
  3. (*arr[5])(int) → 指针指向函数
  4. int *(*arr[5])(int) → 函数返回 int*

十五、指针使用的注意事项

  1. 野指针:未初始化的指针可能会指向随机地址,使用前必须进行初始化。
  2. 内存泄漏:动态分配的内存使用完毕后,一定要用free释放。
  3. 越界访问:对指针进行加减运算时,要确保其指向的是有效内存区域。
  4. 空指针:可以将指针赋值为NULL,以此来表示其不指向任何对象。

十六、常见错误示例

int *p;
*p = 10;           // 错误:野指针解引用
int arr[3];
arr++;            // 错误:数组名是常量指针,不能修改

posted @ 2025-06-27 13:12  RaLi  阅读(0)  评论(0)    收藏  举报  来源