如何使用va_arg“提取”一个长双倍?

时间:2018-11-23 17:36:40

标签: c types variadic

我正在学习C编程并遇到问题。我想从参数列表中“提取”一长串双精度字。但是,当我要求va_arg“捕获”一个长双精度参数时,我会遇到一个随机错误(正如该男子在va_arg错误调用中所提到的那样)。 但是我怎么可能解决这个问题呢? 这是说明pb的代码示例:

void func(va_list *ptr)
{
    long double f;

    f = va_arg(*ptr, long double);
    printf("Value extracted: %Lf\n", f);
    return ;
}

void func2(char *format, ...)
{
    va_list ap;

    va_start(ap, format);
    func(&ap);
    va_end(ap);
    return ;
}

感谢您的帮助!

编辑:我知道如何使用va_arg(至少对于简单的东西而言)。如您所见,该函数将指向va_list的指针作为参数。这是因为我在调用函数中调用了va_start(在同一调用函数的末尾调用了va_end)。我只是想向您展示问题而已。

我对其他数据类型(int,long,char,char *等)没有问题。只是一个长的双倍铅。

编辑#2:我编写了一个调用函数,以向您展示我不会忘记va_start和va_end。最后,我的问题是我正在尝试编写自己的printf函数,并且正在处理-Lf转换。我认为没有必要提起它,对此感到抱歉。

2 个答案:

答案 0 :(得分:1)

您的代码有很多问题,包括缺少va_startva_end,但要解决您的特定问题:

va_arg函数希望在调用该类型时知道该类型;类型参数是 you 告诉它“嘿,参数是这种类型”,而不是“获取具有这种类型的列表中的下一个参数”,我猜这是基于在你的问题上。

通常,在程序集级别上,在将类型传递给函数时,实际上并没有任何有关类型的信息-无需调试信息。这就是va_arg需要该参数的原因,以及printfscanf之类的可变函数需要有关以其格式字符串进行处理的类型的信息的原因。

如果设计的可变参数函数的类型可能有所不同,则需要考虑不同的可能类型。格式字符串是一种方法。

答案 1 :(得分:0)

您仍然没有向我们展示您正在使用的完整的可编译代码,因此很难看出您做错了什么。这是一些完整的代码,它们说明了您要执行的操作。

#include <stdarg.h>
#include <stdio.h>

void vlist_one_ldouble(va_list *pargs) {
    long double value;

    value = va_arg(*pargs, long double);
    printf(" %Lf", value);
}

void vlist_ldouble(int count, va_list *pargs) {
    printf("Now printing %d long doubles:\n", count);

    for (int i=0; i<count; i++)
        vlist_one_ldouble(pargs);

    printf("\n");
}

void list_ldouble(int count, ...) {
    va_list args;
    va_start(args, count);

    vlist_ldouble(count, &args);

    va_end(args);
    return;
}

int main(void) {
    long double a = 1.1, b=2.2, c=3.3;

    list_ldouble(3, a, b, c);
    list_ldouble(4, 1.1L, 2.2L, 3.3L, 4.4L);

    return 0;
}

如果没有完整的代码,我们将无法检查的一个非常重要的事情是,您必须确保实际上传递的是双精度双打。在这里,我有两种方式:首先,使用长双精度变量;其次是长双字面量。

此处的L后缀是“键入文字”的示例。当您在源代码中指定变量的实际值时(例如13.14'b'"foo"),这就是文字。通常,您不必显式指定文字的 type 是什么,因为编译器可以执行任何必要的转换。对于浮点文字,标准说明如下:

  

不带后缀的浮点常量的类型为 double 。如果后缀   字母 f F ,其类型为 float 。如果以   字母 l L ,其类型为 long double

如果使用字面值调用带有原型的标准函数,例如说func(1.2),则编译器将知道func()期望的是float,double还是long double并传递适当的类型功能。但是,由于使用了变长参数列表函数,因此没有可用的原型,因此编译器可以根据您传递的值的类型进行工作。如果您传递的是1.2,它将以双精度形式传递。如果要传递长双精度数,则必须指定1.2实际上是一个长双精度数,这就是L的目的。如果您最终获得双倍奖励,但期望获得长双倍奖励,那么您将无法获得期望的价值。

为此,我找不到理想的参考,但是this page不错,these pages不错,但是都是C ++而不是C。

如果这不能解决您的问题,请发布一个完整的,可编译的程序,该程序未达到您的期望。