自定义printf没有va_list

时间:2013-03-14 21:02:31

标签: c

我正在尝试创建printf()的简化版本,但不使用va_list,va_start,va_arg和va_end。

我最初的想法是:

  
    

void my_printf(char * format,...);

  

然后,浏览格式,并计算%(参数)的数量,以找出传递给我的函数的变量数量。从那里开始,我考虑根据有多少个参数创建一个缓冲区,然后组合然后使用write()最终输出它们。

有没有更好的方法来解决这个问题?我的计划会遇到问题吗?

非常感谢任何帮助。

我的一些头脑风暴代码是:

// Count arguments
int cnt_s, cnt_c, cnt_d, cnt_u, cnt_x;
for (; *format; format++) {
    switch(format[0]) {
        case '%':
            switch(format[1]) {
                case 'd':
                    cnt_d++;
            }
    }
}

2 个答案:

答案 0 :(得分:3)

需要 va_listva_startva_argva_end才能访问...指定的参数

除非您想使用void*和工会----- UGH!

答案 1 :(得分:3)

我能想到的最好的方法(注意:这可能是不安全的)是获取格式字符串的地址并从中增加以查找参数。

下面是我一起攻击的一个工作示例(假设实现了其他打印功能)

int my_printf(char *format, ...) {
    void *beg = &format;
    int i;
    beg += sizeof(char*);
    for (i = 0; i < strlen(format); i++) {
        if (format[i] == '%') {
            switch (format[i+1]) {
                case 's':
                    print_s(*((char**)beg)); 
                    beg += sizeof(char*);
                    break;
                case 'd':
                    print_d(*((int*)beg)); 
                    beg += sizeof(int);
                    break;
                case 'f':
                    print_f(*((float*)beg)); 
                    beg += sizeof(float);
                    break;
            }
            i++;
        } else {
            putchar(format[i]);
        }
    }
}

如果您没有提供足够的参数,这可能会导致一些意外的副作用,并且可能需要进行一些调整。但这就是想法。

说明: 这是有效的,因为所有函数参数都按顺序推送到堆栈中。因此,由于您有第一个参数(格式字符串),您可以根据所需的参数获取其地址并递增,以直接访问堆栈中的参数,而不会产生任何VA_ARGS魔法。