今天本来想定位下项目中日志打印部分的错误,尝试在变参的个数匹配不上时,编译给出warning或error,可惜弄了半天也没实现。
个人测试实现的变参函数代码如下,虽是测试代码,但也基本写明了变参的实现过程,需要注意的问题和相关要点都写在注释中了,下面上代码。
如果有哪位大侠能够给出我上面提到的warning和error的生成建议,欢迎留言或给我私信交流。废话少说,上代码了,可以直接g++ variable_arg.cpp编译成功。
/*
* File: variable_arg.cpp
* Author: Carl
*
* Created on August 28, 2012, 5:25 PM
*/
#include <cstdlib>
#include <cstdio>
#include <stdarg.h>
#include <cstring>
using namespace std;
/*
* 1)C标准规定实现可变参数机制的函数至少要有一个固定参数。
* 2)隐式类型不可用。例如,va_arg指定了类型是double,若传入的是int类型的变量10,就会报错
* 3)C语言的整型提升原则。也就是说,在va_arg中获取float和double使用的type是double,而获取char,short和int使用的type是int
* 4)函数指针不可用,除非用typedef定义过
*/
void miniprintf(const char *fmt, ...)
{
va_list ap; //声明一个对象,用来盛放参数,一个char链表(实际应该是一个连续的内存块,像数组一样),表现为一个指向char类型的指针
int d;
char c, *p, *s;
double f;
//初始化va_list,通过最后的固定参数实现对可变参数初始位置的定位,并未va_list分配内存,将可变参数复制到该内存块中,是va_list指向给内存块的初始位置
va_start(ap, fmt); //ap指向第一个(不是第0个)参数,fmt后面的那个
while (*fmt)
{
if (*fmt != '%') //普通字符直接输出
{
putchar(*fmt++);
continue;
}
fmt++; //格式化字符,++指向s,d之类的格式字符位
switch (*fmt++) //此处的++,目的是指向格式字符位的下一位,为下次loop准备
{
//根据相应格式来取到对应的匹配参数
case 's':
//va_arg,通过移动指针va_list获取由参数type(第二个参数)指定的变量,并返回该变量
s = va_arg(ap, char *);
printf("%s", s);
break;
case 'd':
d = va_arg(ap, int);
printf("%d", d);
break;
case 'c':
c = (char) va_arg(ap, int);
printf("%c", c);
break;
case 'f':
f = va_arg(ap, double);
printf("%f", f);
break;
default: //不被支持的格式字符
printf("the format [%c] is not supported", *fmt);
break;
}
}
va_end(ap); //这个最好都要调用一次,在有的C实现中,可能用来释放va_start为va_list分配的内存
return;
}
double sum(int lim, ...)
{
va_list ap;
double total = 0;
int i;
va_start(ap, lim);
for (i = 0; i < lim; i++)
{
total += va_arg(ap, double); //依次取到每个参数
}
va_end(ap);
return total;
}
int main(int argc, char** argv)
{
char str[10];
memset(str, 0, sizeof (str));
memcpy(str, "hello", 5);
miniprintf("this is the string \"%s\", \nthis is the int %d, \nthis is the character %c\n", str, 3, 'a');
double total = 0;
total = sum(5, 10.0, 20.0, 30.0, 40.0, 50.0); //这里如果是10,20这种int型的数据,会得到错误的结果
miniprintf("total is %f\n", total);
return 0;
}
运行结果如下
this is the string "hello",
this is the int 3,
this is the character a
total is 150.000000
水平有限,如果有朋友发现错误,欢迎留言交流。
转载请保留本文链接,如果觉得我的文章能帮到您,请顶一下。,谢谢。