C语言 - 输出参数详解:从简单示例到 alloc_chrdev_region

发布于:2025-09-01 ⋅ 阅读:(14) ⋅ 点赞:(0)

C语言中的输出参数详解:以 alloc_chrdev_region 为例

在学习 C 语言函数调用时,我们常常接触到“输入参数”,比如把一个数字传给函数,让函数帮我们算出结果。但有时候可能会发现,有些函数除了返回值之外,还会让我们传一个指针参数进去,用来返回额外的结果。这类指针参数就叫 输出参数

本文将从零理解输出参数的概念,先从一个简单的例子入手,再结合 Linux 驱动开发中的 alloc_chrdev_region 函数做深入解析。

一、什么是输出参数?

在 C 语言中,函数有一个返回值,但有时候我们希望函数能够返回多个结果。这时候,就可以通过 指针 把结果写回给调用者,这个指针参数就是输出参数。

  • 输入参数:函数从调用者那里获取的值。
  • 输出参数:函数通过指针写回调用者的值。

简而言之:输入参数进函数,输出参数出函数。

二、一个简单的例子

假设我们要写一个函数:给定一个整数,计算它的平方和两倍,并返回给调用者。

错误思路:只能返回一个值

int calc(int x) {
    return x * x;  // 只能返回平方,没法返回两倍
}

这样只能返回一个结果,不够用。

正确思路:用输出参数

#include <stdio.h>

void calc(int x, int *square, int *twice) {
    *square = x * x;   // 通过指针写回平方
    *twice  = x * 2;   // 通过指针写回两倍
}

int main() {
    int s, t;
    calc(5, &s, &t);
    printf("平方 = %d, 两倍 = %d\n", s, t);
    return 0;
}

运行结果:

平方 = 25, 两倍 = 10

在这里:

  • int *square, int *twice输出参数
  • 函数通过 *square*twice 把结果写回。

这样,函数就相当于“返回了多个结果”。

三、Linux 驱动开发中的例子:alloc_chrdev_region

在 Linux 字符设备驱动开发中,我们经常会调用 alloc_chrdev_region 来向内核申请一个设备号。

函数原型

int alloc_chrdev_region(dev_t *dev, unsigned baseminor,
                        unsigned count, const char *name);

参数说明:

  • dev:输出参数,指向 dev_t 变量,用来存放分配到的设备号。
  • baseminor:起始次设备号。
  • count:需要的设备数量。
  • name:设备名称,会显示在 /proc/devices

返回值:

  • 0 表示成功。
  • 小于 0 表示失败。

使用示例

#include <linux/fs.h>

static dev_t dev_num;  // 保存分配到的设备号

int result = alloc_chrdev_region(&dev_num, 0, 1, "hello_drv");
if (result < 0) {
    printk("分配设备号失败!\n");
} else {
    printk("成功分配到设备号:主设备号=%d, 次设备号=%d\n", MAJOR(dev_num), MINOR(dev_num));
}

这里:

  • &dev_num 作为输出参数传给函数。
  • 内核在函数内部写入分配好的设备号到 *dev,也就是 dev_num
  • 我们调用 MAJOR(dev_num)MINOR(dev_num) 就能拿到主次设备号。

为什么要用输出参数?

因为 alloc_chrdev_region 既要告诉我们“执行成功还是失败”,又要把“分配到的设备号”返回回来。一个返回值不够用,所以就把设备号通过输出参数返回。

四、总结

  1. 输出参数的本质:通过指针让函数“返回”额外的结果。
  2. 适用场景:当一个函数需要返回多个值时。
  3. 简单例子:计算平方和两倍,用指针参数返回。
  4. 实际应用alloc_chrdev_region 用输出参数返回分配到的设备号。

总结:

返回值表示成功与否,输出参数返回结果数据。

这就是为什么 alloc_chrdev_regiondev_t *dev 参数一定要传指针的原因。


(完)


网站公告

今日签到

点亮在社区的每一天
去签到