C-奇怪的输出迭代va_list变量



我想编写一个函数,其任务仅打印输入向量的非负组件。

所以,我的第一次尝试是:

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#define BIG_INT 100
void print_nonnegatives(int arg1, ...)
{
    va_list ap;
    va_start(ap, arg1);
    for (int i = arg1; -BIG_INT < i && i < BIG_INT; i = va_arg(ap, int))
    {
        if (i >= 0)
        {
            printf("%d ", i);
        }
    }
    va_end(ap);
    puts("n");
}
int main()
{
    print_nonnegatives(1, 3, -4, 5, 6);
    print_nonnegatives(-1);
    print_nonnegatives(7, -1, -1, 9);
}

它有效;但是有一些肮脏的线条。例如,如果其中一个参数大于big_int,则将失败。

我尝试更改条件-Big_int&lt;i&amp; amp;i&lt;big_int逃脱了这种失败。因此,我用i/i == 1代替了它。我的主要问题是什么是奇怪的输出以及它们来自何处?

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#define BIG_INT 100
void print_nonnegatives(int arg1, ...)
{
    va_list ap;
    va_start(ap, arg1);
    for (int i = arg1; i / i == 1; i = va_arg(ap, int))
    {
        if (i >= 0)
        {
            printf("%d ", i);
        }
    }
    va_end(ap);
    puts("n");
}
int main()
{
    print_nonnegatives(1, 3, -4, 5, 6);
    //print_nonnegatives(-1);
    //print_nonnegatives(7, -1, -1, 9);
}

"不良输出"来自以下事实:您不会通过参数结束参数列表。

当您到达参数列表的结尾时,va_arg函数不会自动返回某种"参数列表"值,而是只会为您提供Infinity中的"下一个"参数。这意味着您将超越参数列表的末尾,并具有未定义的行为。

您需要传递比BIG_INT更大或更小的值以结束参数列表(显示的第一个示例)。

您必须告诉您的函数您传递了多少个int-第一个参数可以说明这一点。顺便说一句 - 这是第一个参数,因为当使用" CDECL"调用惯例时,第一个参数已知和固定位置,因此" Callee"可以使用它来确定在堆栈上推出了多少东西作为参数。您可能会这样做:

#include <cstdarg>
#include <iostream>
void print(int howMany, ...)
{
    va_list args;
    va_start(args, howMany);
    while(howMany--)
    {
        int nextNum = va_arg(args, int);
        if (nextNum > 0) std::cout << nextNum << std::endl;
    }
    va_end(args);
}

int main()
{
    print(9 /*tells how many ints follows*/, 10,-20,30,40,-50,60,-70,80,90);
}

最新更新