【问题标题】:Custom printf without va_list没有 va_list 的自定义 printf
【发布时间】:2013-03-03 10:37:36
【问题描述】:

我正在尝试创建 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++;
            }
    }
}

【问题讨论】:

  • 需要va_listva_startva_argva_end来访问...指定的参数
  • 我正在考虑直接从内存中访问它们。那么除了...,我还能用什么?
  • 这是一个非常糟糕的主意。 为什么您试图规避为访问可变长度参数数组提供的标准方法?
  • 它不适用于任何实际应用。

标签: c


【解决方案1】:

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

这是我一起编写的一个工作示例(假设实现了其他打印功能)

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 魔法。

【讨论】:

    【解决方案2】:

    需要va_listva_startva_argva_end 来访问... 指定的参数

    除非你想使用 void* 和 unions-----UGH!

    【讨论】:

    • 将一个联合数组传递给你的函数(void* 是个脑残)……但你真的想要va_arg 和朋友们!
    • 如果我可以使用 va_list 而我不会使用什么,但在这种情况下我无法使用。该函数将使用 my_printf(format, arg1, arg2, arg3, ect) 调用。我将如何在不使用 va_list 的情况下获取这些参数,而不是什么?我正在考虑使用无论作为起始内存位置提供的格式 var,然后计算格式中列出的 args 的数量,然后从起始位置(格式)跳到内存并获取每个变量。有更好的方法吗?
    • my_printf_d(format, intval), my_printf_f(format, doubleval), my_printf_dddfd(format, intval1, intval2, intval3, doubleval, intval4) ...
    • @Pat:您所描述的正是 va_start 和朋友们以便携的方式为您所做的事情。
    猜你喜欢
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 2018-06-25
    相关资源
    最近更新 更多