奇怪的输出迭代va_list变量

时间:2019-03-22 07:47:08

标签: c variadic-functions

我想编写一个带有未知整数成员的函数,并且仅输出它们的非负数。更准确地说,这些是样本 我最喜欢的输出:

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

#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进行编译。

2 个答案:

答案 0 :(得分:0)

“输出错误”是由于您没有传递参数来结束参数列表。

当您到达参数列表的末尾时,va_arg函数不会自动返回某种“参数列表末尾”值,而是只会为您提供无穷大的“下一个”参数。这意味着您将超出参数列表的末尾,并拥有undefined behavior

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

答案 1 :(得分:0)

您必须告诉您的函数要传递给它多少个整数-第一个参数可以告诉您。顺便说一句-它必须是第一个参数,因为当使用'cdecl'调用约定时,第一个参数在堆栈框架中是已知且固定的位置,因此'callee'可以使用它来确定将多少内容作为参数压入堆栈。您可以这样做:

el.onpointerdown = ev => {
    el.onpointermove = pointerMove 
    el.setPointerCapture(ev.pointerId)
}

pointerMove = ev => {
    console.log('Dragged!')
}

el.onpointerUp = ev => {
    el.onpointermove = null
    el.releasePointerCapture(ev.pointerId)
}