《C语言程序设计》笔记7
变参函数
- 形如int max_int(int a, …);参数列表中含有变参列表“…”(这不是省略号),a是…变参列表中参数的个数
- 变参列表的实现是借助va一族:
“函数” | 功能 |
---|---|
va_list | 获得a往后的参数列表 |
va_start | 定位a后面第一个参数的位置 |
va_arg | 获取下一个可变参数列表中的参数 |
va_end | 销毁list,结束整个获取可变参数列表的动作 |
- 以上不是严格意义上的函数,因为以上函数把类型当作形参,而这个功能函数是无法实现的,只能借助宏定义来完成
- 头文件:stdarg.h
变参函数的应用
求一系列数字的最大值
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#define INT32_MIN -pow(2, 31)
#define INT32_MAX pow(2, 31) - 1
int max_int(int n, ...) {
int ans = INT32_MIN;
va_list arg;
va_start(arg, n);
while (n--) {
int temp = va_arg(arg, int);
if (temp > ans) ans = temp;
}
va_end(arg);
return ans;
}
int main() {
printf("%d\n", max_int(3, 1, 2, 3));
printf("%d\n", max_int(5, 1, 2, 3, 24, -1));
return 0;
}
运行结果:
- 在第12行va_arg(arg, int)若变参列表的参数分别是char a, int b, double c则根据这个“函数”的功能只能取到b
- inttypes.h头文件下的宏定义INT32_MIN和INT32_MAX在我的编译器上(CodeBlocks)没反应,还没搞清楚有没有这俩玩意儿
- 上面的代码体现读取变参列表的过程:创建list→取第一个形参的地址→获取变参列表中下一个形参→销毁list,最后一步是一个习惯,就像创建指针最后要销毁指针一样
自制printf函数
- printf底层是用putchar()一个一个打印字符实现的,输出流cin是用printf来实现的,因此自制printf函数中用putchar()来实现
- 以下是简单输出字符串
#include <stdio.h>
//#include <stdarg.h>
#include <string.h>
int my_printf(const char *frm, ...) {
int cnt = 0;
for (int i = 0; i < strlen(frm); i++) {
putchar(frm[i]), cnt++;
}
return cnt;
}
int main() {
my_printf("Hello world\n");
return 0;
}
- 那么要输出整型变量:
#include <stdio.h>
#include <stdarg.h>
//#include <string.h>
int my_printf(const char *frm, ...) {
int cnt = 0;
va_list arg;
va_start(arg, frm);
#define PUTC(a) putchar(a), cnt++
for (int i = 0; frm[i]; i++) {
switch (frm[i]) {
case '%': {
switch (frm[++i]){
case '%':
PUTC(frm[i]);
break;
case 'd': {
int x = va_arg(arg, int);
char num[16] = {0};
int k = 0;
while (x) {
num[k++] = x % 10 + '0';
x /= 10;
}
while (k > 0) {
PUTC(num[--k]);
}
}break;
}
}break;
default:
PUTC(frm[i]);
}
}
return cnt;
}
int main() {
int a = 123;
my_printf("Hello world\n");
my_printf("%%%d", a);
return 0;
}
- 上面的代码只是一个简易版的printf函数,整数的输出可能还有一些bug,当然了,最重要的是深入理解printf的底层实现过程!
- 同理scanf函数的简易实现是借助getchar()来完成的