奇怪的输出迭代 va_list 个变量
Strange output iterating va_list varibles
我想编写一个包含未知整数成员的函数,并且只打印它们的非负数。更准确地说,这些是样本
我最喜欢的输出:
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 进行编译
"bad output" 是因为您没有传递参数来结束参数列表。
当您到达参数列表的末尾时,va_arg
函数不会自动 return 某种 "end of argument list" 值,相反它只会给您 "next" 无限论证。这意味着您将超出参数列表的末尾并具有 undefined behavior.
您需要传递一个大于或小于 BIG_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);
}
我想编写一个包含未知整数成员的函数,并且只打印它们的非负数。更准确地说,这些是样本 我最喜欢的输出:
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 进行编译"bad output" 是因为您没有传递参数来结束参数列表。
当您到达参数列表的末尾时,va_arg
函数不会自动 return 某种 "end of argument list" 值,相反它只会给您 "next" 无限论证。这意味着您将超出参数列表的末尾并具有 undefined behavior.
您需要传递一个大于或小于 BIG_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);
}