当前位置: 首页 > article >正文

C 语言学习七:指针

指针

  • 指针与地址
    • 指针的声明和初始化
    • 指针的解引用
    • 指针的比较
    • 指针和数组
    • 指针数组
    • 指针和动态内存分配
  • 指针与函数参数
    • 指针作为函数参数
    • 二级指针
  • 指向函数的指针

指针与地址

指针的声明和初始化

int variable = 42;
int *ptr = &variable;
//间接访问
int value = *ptr; // value 等于 x 的值,即 42

char str[] = "Hello"; // 字符串数组
const char* ptr = "World";  // 字符串指针
  • 空指针:未指向任何对象的指针

    int *ptr = NULL;
    

指针的解引用

通过指针可以访问或修改其指向的变量的值,通过使用解引用操作符 * 完成。

int value = *ptr;  // 通过指针获取变量的值
*ptr = 10;         // 通过指针修改变量的值

指针的比较

指针可以进行大小比较,但要注意指针比较的是地址而不是指向的值

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
int main() {
    int arr[5] = { 1, 2, 3, 4, 5 };
    int* ptr1 = arr;
    int* ptr2 = arr + 2;
    printf("*ptr1=%d\n", *ptr1);
    printf("*ptr2=%d\n", *ptr2);
    printf("ptr1=%d\n", ptr1);
    printf("ptr2=%d\n", ptr2);
    if (ptr1 < ptr2) {
        // 执行此处代码
    }
    return 0;
}

在这里插入图片描述

指针和数组

指针可以进行算术运算,例如指针加法和指针减法。在数组遍历和动态内存管理中非常有用(区分开地址和值的变化

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>

int main() {
    int arr[5] = { 1, 2, 3, 4, 5 };
    int* ptr = arr;
    // 指针加法
    ptr = ptr + 2; // 移动两个元素
    *ptr = *ptr - 1;	//值变化
    printf("*ptr=%d", *ptr);
    // 现在 ptr 指向 arr[1]
    return 0;
}

指针数组

  1. 定义: 指针数组是一个数组,其元素都是指针

    int *ptrArray[5]; // 声明一个包含 5 个指针的数组
    
  2. 初始化:指针数组的每个元素必须指向相同类型或相同结构的数据

    int a = 5, b = 10, c = 15;
    int *ptrArray[3] = {&a, &b, &c}; // 初始化指针数组
    
  3. 使用:当需要一次性操作多个相关的指针,而这些指针的数量可能在运行时发生变化时,使用指针数组能够更方便地管理这些指针。

指针和动态内存分配

malloc、calloc、realloc 和 free 等函数用于动态内存分配和释放,返回的是指向动态分配内存的指针。

int *dynamicArray = (int *)malloc(5 * sizeof(int));

指针与函数参数

指针作为函数参数

  • 函数可以接受指针作为参数,允许函数修改调用者提供的变量的值

    void modifyValue(int *ptr) {
        *ptr = 100;
    }
    
    int main() {
        int value = 42;
        modifyValue(&value);
        // 此时 value 的值变为 100
    }
    
  • 同样的也可以修改数组的元素

    void modifyArray(int *arr, int size) {
        for (int i = 0; i < size; ++i) {
            arr[i] *= 2;
        }
    }
    
    int main() {
        int arr[] = {1, 2, 3, 4, 5};
        modifyArray(arr, 5);	//数组名就是数组的首地址
        // 此时 arr 变为 {2, 4, 6, 8, 10}
    }
    

二级指针

动态分配内存为例
当传递一个指针给函数时,传递的是指针的拷贝。如果在函数内部分配了新的内存,并将这个新内存的地址赋给传入的指针,这对于调用者的指针没有影响。为了解决这个问题,可以传递一个指针的指针,也就是二级指针

void allocateMemory(int **ptr) {
    *ptr = (int *)malloc(sizeof(int));
    **ptr = 42;
}

int main() {
    int *dynamicValue;
    allocateMemory(&dynamicValue);
    // 此时 dynamicValue 指向了动态分配的内存,其值为 42
}

int **ptr 表示一个指向指针的指针。这是为了能够在函数内部修改指针的值。

指向函数的指针

  1. 定义函数指针:函数指针的声明形式类似于函数声明,只需在函数名前面加上指针类型,例如int (*ptr)(int, int);表示 ptr 是一个指向接受两个整数参数并返回整数的函数的指针

  2. 初始化函数指针:ptr = &add;其中 add 是一个函数,ptr 就指向了这个函数

  3. 用途:
    回调函数: 当你需要在某个地方注册一个函数,以便在特定事件发生时调用它时,函数指针就非常有用。例如,你可能有一个事件处理器,允许用户注册一个函数,然后在某个事件发生时调用该函数

    // 使用函数指针实现回调
    void eventHandler(void (*callback)(int)) {
        // 做一些操作
        int data = 42;
        // 调用注册的回调函数
        callback(data);
    }
    
    // 注册的回调函数
    void myCallback(int value) {
        printf("Callback called with value: %d\n", value);
    }
    
    int main() {
        // 在事件处理器中注册回调函数
        eventHandler(myCallback);
    
        return 0;
    }
    

http://www.kler.cn/a/234069.html

相关文章:

  • 高频 SQL 50 题(基础版)连接部分
  • 【系统设计】数据库压缩技术详解:从基础到实践(附Redis内存优化实战案例)
  • RT-DETR融合CVPR[2020]轻量化卷积模块Ghost Module模块
  • JavaScript Cookie 与 服务器生成的 Cookie 的区别与应用
  • git之 revert和rebase
  • ESLint 使用教程(七):ESLint还能校验JSON文件内容?
  • 【MySQL题】——基础概念论述(二)
  • 基于YOLOv8算法的照片角度分类项目实践
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Web组件
  • 【制作100个unity游戏之23】实现类似七日杀、森林一样的生存游戏10(附项目源码)
  • 【力扣 51】N 皇后(回溯+剪枝+深度优先搜索)
  • 算法学习——LeetCode力扣二叉树篇2
  • 2024.1.31力扣每日一题——找出不同元素数目差数组
  • JAVA面试题11
  • 基于PSO粒子群优化的PID控制器参数整定算法matlab仿真
  • 算法练习-四数之和(思路+流程图+代码)
  • 【linux系统体验】-archlinux折腾日记
  • Java 内存区域介绍
  • 如何为Kafka加上账号密码(二)
  • Android---Jetpack Compose学习002
  • BUUCTF-Real-[Tomcat]CVE-2017-12615
  • 命令行随笔
  • 《计算思维导论》笔记:10.4 关系模型-关系运算
  • JRT监听程序
  • 爬虫练习——动态网页的爬取(股票和百度翻译)
  • Jetpack Compose常用工具包推荐