C语言指针(二)

🌟 各位看官好,我是maomi_9526

🌍 种一棵树最好是十年前,其次是现在!

🚀 今天来学习C语言的相关知识。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

目录

1. 字符指针变量

2. 数组指针变量

3. 二维数组传参的本质

4. 函数指针变量

5. 函数指针数组

6. 转移表

7. 回调函数

9.qsort 函数模拟实现

10.typedef 关键字

1. 字符指针变量

  • 定义:字符指针 char* 用于存放字符类型变量的地址。

  • 例子1

    char ch = 'w';
    char *pc = &ch;
    *pc = 'w';
    
  • 例子2:常量字符串的字符指针

    const char* pstr = "hello bit.";
    printf("%s\n", pstr);
    
    • 解释:pstr 存储的是字符串 "hello bit." 的首字符地址,而不是字符串本身。
  • 比较字符串

    char str1[] = "hello bit.";
    char str2[] = "hello bit.";
    const char *str3 = "hello bit.";
    const char *str4 = "hello bit.";
    
    • 结果:str3str4 指向相同的内存区域,而 str1str2 存储在不同的内存块。
2. 数组指针变量
  • 定义:数组指针变量是指向数组的指针,指向整个数组而非数组元素。

  • 例子

    int (*p)[10] = &arr;
    
    • p 是一个指向包含 10 个整数的数组的指针。
  • 数组指针的初始化:数组指针指向数组的地址。

    int arr[10] = {0};
    int (*p)[10] = &arr;
    
3. 二维数组传参的本质
  • 传参方式:二维数组可以通过数组指针或者数组名传递。
    • 形参为数组
      void test(int a[3][5], int r, int c)
      
    • 形参为指针
      void test(int (*p)[5], int r, int c)
      
    • 解释:二维数组传递本质上是传递第一行的地址,数组名表示的是第一行的地址。
4. 函数指针变量
  • 定义:函数指针变量是用来存储函数地址的指针,可以通过该指针调用函数。

  • 创建函数指针

    void (*pf)() = &test;
    
    • 也可以省略 &,直接使用函数名来赋值。
  • 调用函数

    (*pf)();
    
    • 或者直接使用 pf()
  • 函数指针的解析

    • int (*pf3)(int, int) 表示 pf3 是一个指向返回 int 类型并接受两个 int 类型参数的函数的指针。
5. 函数指针数组
  • 定义:函数指针数组是一个数组,其中每个元素都是一个函数指针。
  • 定义方法
    int (*parr1[3])();
    
  • 例子:用函数指针数组实现计算器功能:
    int (*p[5])(int, int) = {0, add, sub, mul, div};
    
6. 转移表
  • 定义:转移表利用函数指针数组实现条件分支结构,例如计算器的实现。
  • 例子
    int (*p[5])(int, int) = { 0, add, sub, mul, div };
    
  • 通过用户输入选择对应的计算操作,调用相应的函数。
7. 回调函数
  • 定义:回调函数是指通过函数指针传递并在需要时调用的函数。
  • 例子:改造计算器,使用回调函数来简化代码:
    void calc(int(*pf)(int, int))
    {
        int ret = 0, x, y;
        printf("输入操作数:");
        scanf("%d %d", &x, &y);
        ret = pf(x, y);
        printf("ret = %d\n", ret);
    }
    
9.qsort 函数模拟实现

为了模拟 qsort 函数的排序功能,可以使用回调函数和冒泡排序的方式。利用 void* 类型的指针,我们可以实现通用排序函数,支持排序不同类型的数据。

代码实现:

#include <stdio.h>

int int_cmp(const void *p1, const void *p2) {
    return (*(int *)p1 - *(int *)p2);  // 整数比较函数
}

void _swap(void *p1, void *p2, int size) {
    int i;
    for (i = 0; i < size; i++) {
        char tmp = *((char *)p1 + i);  // 逐字节交换数据
        *((char *)p1 + i) = *((char *)p2 + i);
        *((char *)p2 + i) = tmp;
    }
}

void bubble(void *base, int count, int size, int (*cmp)(void *, void *)) {
    int i, j;
    for (i = 0; i < count - 1; i++) {
        for (j = 0; j < count - i - 1; j++) {
            if (cmp((char *)base + j * size, (char *)base + (j + 1) * size) > 0) {
                _swap((char *)base + j * size, (char *)base + (j + 1) * size, size);
            }
        }
    }
}

int main() {
    int arr[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
    int i;

    int arr_size = sizeof(arr) / sizeof(arr[0]);
    bubble(arr, arr_size, sizeof(int), int_cmp);  // 使用冒泡排序

    // 输出排序后的结果
    for (i = 0; i < arr_size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

代码解释:

  1. int_cmp 函数:这是一个用于比较两个整数的函数,返回比较结果,适用于 qsort 或者 bubble 函数的回调。

  2. _swap 函数:用于交换两个 void* 类型指针指向的内存块的数据。它逐字节交换数据,确保通用性。

  3. bubble 函数:实现冒泡排序的核心逻辑。它接受 void* 类型的指针,可以排序任意类型的数据,比较函数和数据类型通过 void* 指针传递。

输出示例:

0 1 2 3 4 5 6 7 8 9
10.typedef 关键字

typedef 关键字用于为已有的类型定义一个新的名字。这样可以提高代码的可读性,简化复杂类型的书写。typedef 可以用于基本数据类型、指针、数组、结构体等。

代码示例:

#include <stdio.h>

// 使用 typedef 创建类型别名
typedef unsigned int uint;    // 将 unsigned int 重命名为 uint
typedef int* ptr_t;           // 将 int* 重命名为 ptr_t
typedef void(*pfun_t)(int);   // 将 void(*)(int) 函数指针类型重命名为 pfun_t

int main() {
    uint a = 10;  // uint 等同于 unsigned int
    ptr_t p = &a; // ptr_t 等同于 int*
    
    // 使用 typedef 定义的函数指针类型
    pfun_t func = NULL;
    
    // 输出 a 的值和 p 所指向的值
    printf("a = %u, *p = %d\n", a, *p);

    return 0;
}

代码解析:

  1. typedef unsigned int uint;unsigned int 重命名为 uint

  2. typedef int* ptr_t;int* 重命名为 ptr_t,可以方便地表示指向 int 类型的指针。

  3. typedef void(*pfun_t)(int);void (*)(int) 函数指针类型重命名为 pfun_t,简化了函数指针的定义。

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值