C语言|指针的应用

个人主页-爱因斯晨

文章专栏-C语言

加油哦~各位!

一、指针的本质

  1. 定义:指针是一种变量,专门用于存储内存地址,其大小通常为 4 字节(32 位系统)或 8 字节(64 位系统)

  2. 核心价值

    • 直接操作内存,提升程序执行效率
    • 实现函数多值返回
    • 为动态内存分配提供支持
    • 实现数据结构(链表、树等)
  3. 声明方式数据类型 *指针变量名

    c 复制代码
    int *p;  // 声明一个指向int类型的指针p
    char *str;  // 声明一个指向char类型的指针str

二、指针与地址的关系

  1. 取地址运算符(&):获取变量的内存地址

    c 复制代码
    int a = 10;
    int *p = &a;  // 将变量a的地址赋值给指针p
  2. 解引用运算符(*):通过地址访问变量的值

    c 复制代码
    printf("%d", *p);  // 输出指针p所指向的变量值,即10
    *p = 20;  // 修改指针p所指向的变量值
  3. NULL 指针:不指向任何有效内存的指针

    c 复制代码
    int *p = NULL;  // 初始化空指针
    if (p == NULL) {  // 判断指针是否为空
        // 处理空指针情况
    }

三、指针与变量的结合使用

  1. 指针变量的初始化

    c 复制代码
    int a = 5;
    int *p1;       // 未初始化的指针(野指针,危险!)
    int *p2 = &a;  // 正确初始化,指向变量a
    int *p3 = NULL;  // 初始化为空指针
  2. 指针的运算

    • 指针 ± 整数:移动指针指向的位置
    c 复制代码
    int arr[5] = {1,2,3,4,5};
    int *p = arr;
    p++;  // 指针向后移动一个int类型的大小(通常4字节)
    • 指针 - 指针:计算两个指针之间的元素个数
    c 复制代码
    int len = &arr[4] - &arr[0];  // 结果为4(元素个数差)
  3. 多级指针:指向指针的指针

    c 复制代码
    int a = 10;
    int *p = &a;    // 一级指针
    int **pp = &p;  // 二级指针
    printf("%d", **pp);  // 输出10

四、指针与数组的关系

  1. 数组名的特性:数组名代表数组首元素的地址(常量指针)

    c 复制代码
    int arr[5] = {1,2,3,4,5};
    printf("%p", arr);    // 输出数组首元素地址
    printf("%p", &arr[0]);  // 与上面输出相同
  2. 指针访问数组元素

    c 复制代码
    // 以下两种方式等价
    arr[2] = 10;
    *(arr + 2) = 10;
  3. 数组指针(指向数组的指针)

    c 复制代码
    int (*p)[5];  // 指向包含5个int元素的数组的指针
    int arr[5] = {1,2,3,4,5};
    p = &arr;  // p指向整个数组
  4. 指针数组(元素为指针的数组)

    c 复制代码
    int *p[5];  // 包含5个int*指针的数组
    int a = 1, b = 2, c = 3;
    p[0] = &a;
    p[1] = &b;
    p[2] = &c;

五、指针与函数的关系

  1. 函数参数传递

    • 值传递:函数内部修改不影响外部变量
    • 指针传递:函数内部可修改外部变量
    c 复制代码
    void swap(int *x, int *y) {
        int temp = *x;
        *x = *y;
        *y = temp;
    }
    
    // 调用方式
    int a = 3, b = 5;
    swap(&a, &b);  // a和b的值会被交换
  2. 函数返回指针

    c 复制代码
    int *createArray(int size) {
        int *arr = malloc(size * sizeof(int));
        return arr;  // 返回动态分配内存的指针
    }
  3. 函数指针(指向函数的指针)

    c 复制代码
    int add(int a, int b) {
        return a + b;
    }
    
    int (*funcPtr)(int, int);  // 声明函数指针
    funcPtr = add;  // 函数指针指向add函数
    int result = funcPtr(3, 5);  // 调用函数,结果为8

六、指针与字符串

  1. 字符串的两种表示形式

    c 复制代码
    char str1[] = "hello";  // 字符数组
    char *str2 = "world";   // 字符串常量指针
  2. 指针操作字符串

    c 复制代码
    char *str = "hello";
    while (*str != '\0') {
        printf("%c", *str);
        str++;  // 移动指针访问下一个字符
    }
  3. 字符串处理函数与指针

    c 复制代码
    #include <string.h>
    
    char *src = "hello";
    char dest[20];
    strcpy(dest, src);  // 字符串复制
    int len = strlen(src);  // 获取字符串长度

七、动态内存分配与指针

  1. malloc 函数:分配指定字节数的内存

    c 复制代码
    int *p = (int*)malloc(5 * sizeof(int));  // 分配5个int的内存
    if (p == NULL) {
        // 内存分配失败处理
    }
  2. calloc 函数:分配内存并初始化为 0

    c 复制代码
    int *p = (int*)calloc(5, sizeof(int));  // 分配5个int并初始化为0
  3. realloc 函数:重新调整已分配内存的大小

    c 复制代码
    p = (int*)realloc(p, 10 * sizeof(int));  // 将内存调整为10个int
  4. free 函数:释放动态分配的内存

    c 复制代码
    free(p);  // 释放内存
    p = NULL;  // 避免野指针

八、指针使用的常见错误

  1. 野指针:未初始化的指针或指向已释放内存的指针

    c 复制代码
    int *p;  // 野指针,危险!
    *p = 10;  // 未定义行为
  2. 空指针解引用:对 NULL 指针使用解引用运算符

    c 复制代码
    int *p = NULL;
    *p = 5;  // 程序崩溃
  3. 内存泄漏:动态分配的内存未释放

    c 复制代码
    int *p = (int*)malloc(sizeof(int));
    // 忘记调用free(p),导致内存泄漏
  4. 指针越界:访问超出数组范围的内存

    c 复制代码
    int arr[5];
    int *p = arr;
    p[10] = 3;  // 越界访问,可能导致程序崩溃

九、指针的实际应用场景

  1. 高效处理大型数据:避免数据拷贝,直接传递地址
  2. 实现数据结构:链表、树、图等都依赖指针实现
  3. 函数回调机制:通过函数指针实现事件处理
  4. 动态数据结构:根据需要动态分配和释放内存
  5. 操作硬件设备:直接访问特定内存地址控制硬件
相关推荐
GOATLong3 分钟前
传输层协议TCP
c语言·开发语言·网络·c++·网络协议·tcp/ip
哈基咩11 分钟前
Go语言unsafe包深度解析
服务器·开发语言·后端·golang
天若有情67330 分钟前
从一个“诡异“的C++程序理解状态机、防抖与系统交互
开发语言·c++·交互·面向对象·状态机
武昌库里写JAVA31 分钟前
vue+iview+i18n国际化
java·开发语言·spring boot·学习·课程设计
henreash32 分钟前
xLua和C#交互
开发语言·c#·交互
xzkyd outpaper35 分钟前
Android中ViewStub和View有什么区别?
android·开发语言·面试·代码
悦悦子a啊2 小时前
Python之--集合
开发语言·python·编程
程序员编程指南2 小时前
Qt字符串处理与正则表达式应用
c语言·c++·qt·正则表达式
运维帮手大橙子2 小时前
字符串缓冲区和正则表达式
java·开发语言
慢慢沉3 小时前
Lua(数据库访问)
开发语言·数据库·lua