我目前正在调试我的printf项目的学校,基本上我只需要重做功能,但我遇到了一个问题,我不能理解。
下面是我的代码:
#include "ft_printf.h"
int ft_putchar(int c)
{
write(1, &c, 1);
return (1);
}
int ft_format(va_list args, const char format)
{
if (format == 'c')
return (ft_putchar(va_arg(args, int)));
return (-1);
}
int ft_printf(const char *format, ...)
{
size_t i;
int print_length;
va_list args;
i = 0;
print_length = 0;
va_start(args, format);
while (format[i])
{
if (format[i] == '%')
{
i++;
if (format[i] != '\0')
{
print_length += ft_format(args, format[i]);
}
}
else
print_length += ft_putchar(format[i]);
i++;
}
va_end(args);
return (print_length);
}
int main(void)
{
ft_printf("l%cl%cl%cl%c\n", 'a', 'b', 'c', 'd');
printf("l%cl%cl%cl%c\n", 'a', 'b', 'c', 'd');
}
结果:
ft_printf:lalalala| printf:lalblcld
我不明白为什么当我尝试打印许多参数时它不能正常工作,所以如果有人能帮我找出问题所在。
我尝试过的是:
我尝试添加va_arg(args,int);在调用ft_format后,它工作正常!但是我还是不明白为什么这个例子没有直接在我的ft_format函数中处理?
int ft_printf(const char *format, ...)
{
size_t i;
int print_length;
va_list args;
i = 0;
print_length = 0;
va_start(args, format);
while (format[i])
{
if (format[i] == '%')
{
i++;
if (format[i] != '\0')
{
print_length += ft_format(args, format[i]);
a_arg(args, int);
}
}
else
print_length += ft_putchar(format[i]);
i++;
}
va_end(args);
return (print_length);
}
输出量:
ft_printf:lalblcld| printf:lalblcld
1条答案
按热度按时间mqkwyuun1#
来自C11 7.16变量参数<stdarg.h>:(强调和格式化我的)
声明的类型为
其是适合于保存宏X1 m0n1x、X1 m1n1x、X1 m2n1x和X1 m3n1x所需的信息的完整对象类型。如果需要访问可变参数,则被调用的函数应声明一个类型为
va_list
的对象(在本小节中通常称为 ap)。对象 ap 可以作为参数传递给另一个函数;如果该函数用参数ap调用va_arg
宏,则调用函数中 ap 值是不确定的,且应在进一步引用 ap 之前传递给va_end
宏。和
允许创建指向
va_list
的指针并将该指针传递给另一个函数,在这种情况下,原始函数可以在其他函数返回后进一步使用原始列表。因此,在
ft_format
返回后,必须在args
上调用va_end
,以将其从不确定状态恢复。但是,C11 7.16.1.3 va_end宏也有这样的说法:* (强调和格式化我的)*
va_end
宏有助于从其变量参数列表被va_start
宏的扩展引用的函数或包含va_copy macro
扩展的函数(初始化va_list
ap)正常返回。**va_end
宏可能会修改 ap,使其不再可用(不需要va_start
或va_copy
宏重新初始化)。**如果没有相应的va_start
或va_copy
宏调用,或者在返回之前没有调用va_end
宏,则行为未定义。据我所知你有两个选择
使用
va_copy
创建va_list
对象当前状态的副本并将该对象传递给
ft_format
。或者,将
ft_format
定义为并向它传递指向
va_list
对象的指针和