奇怪的输出迭代va_list变量

问题描述 投票:-1回答:2

我想编写一个具有未知整数成员的函数,并仅打印它们的非负数。更确切地说,这些是我的fravourite输出样本:

print_nonnegatives(1, 3, -4, 5, 6) = 1, 3, 5, 6
print_nonnegatives(-1) = 
print_nonnegatives(7, -1, -4, 9) = 7, 9

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

#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 <i && i <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);
}

值得注意的事实是我在Linux上用gcc编译。

c variadic-functions
2个回答
0
投票

“输出错误”来自于您不传递参数以结束参数列表的事实。

当你到达参数列表的末尾时,va_arg函数不会自动返回某种“参数结束列表”值,而只会在无穷大中给你“下一个”参数。这意味着你将超越参数列表的末尾并拥有undefined behavior

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


0
投票

你必须告诉你的函数你传递了多少个int - 第一个参数可以告诉你。 BTW - 它必须是第一个参数,因为当使用'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);
}
© www.soinside.com 2019 - 2024. All rights reserved.