C语言 - 输出参数详解:从简单示例到 alloc_chrdev_region
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
既要告诉我们“执行成功还是失败”,又要把“分配到的设备号”返回回来。一个返回值不够用,所以就把设备号通过输出参数返回。
四、总结
- 输出参数的本质:通过指针让函数“返回”额外的结果。
- 适用场景:当一个函数需要返回多个值时。
- 简单例子:计算平方和两倍,用指针参数返回。
- 实际应用:
alloc_chrdev_region
用输出参数返回分配到的设备号。
总结:
返回值表示成功与否,输出参数返回结果数据。
这就是为什么 alloc_chrdev_region
的 dev_t *dev
参数一定要传指针的原因。
(完)