集类型的可变长度参数列表

时间:2012-10-07 18:24:56

标签: c++ c function arguments

好吧,我很确定以前已经以某种方式讨论过这个问题,但我发现它显然太愚蠢了。

首先:我不是在寻找va_list和其他宏。 我正在寻找的是主要功能参数。

默认原型,正如你们所知道的那样:

int main(int argc, char *argv[]);

现在,我想要一些与我的程序类似的东西,但不知道究竟是怎么回事。

我们假设我们有这个功能:

void Function(int argc, unsigned short *args[]) {
    for(int i = 0; i < argc; ++i) printf("%hu ", args[i]);
}

我想要这样的函数调用:

Function(5, 1, 2, 3, 4, 5);

那会有用吗? 因为我不想要va_list的“混乱”,也不想创建:

void AnotherFunction() {
    unsigned short Args[] = { 1, 2, 3, 4, 5 };
    Function(5, Args);
}

仅仅因为在这种情况下我只需要一个简单的指针。 有人可以指点我正确的方向吗?非常感谢你。

编辑: 感谢大家的宝贵意见。我会满足于'现在不能使用标准的C / C ++,并寻找一种不同的解决方法。

再次,非常感谢你。

6 个答案:

答案 0 :(得分:3)

由于您还在C中使用C:标记,因此您可以将宏与所谓的复合文字结合使用

#define  FUNCTION(ARGC, ...) (Function((ARGC), (unsigned short[]){ __VA_ARGS__ }))

这类型更安全,因为它将列表中的所有表达式转换为va_list

现代C ++现在还具有宏预处理阶段的unsigned short功能。但我不知道你如何创建一个矢量作为临时值,用值初始化。

答案 1 :(得分:3)

g ++特定解决方案:

const size_t MAX_ARGS = 42;

void Function(int argc, const unsigned short (&args)[MAX_ARGS])
{
}

int main()
{
    Function(5, {1,2,3,4,5});
}

如果您实际上不需要argc参数,则可以编写模板:

template<size_t N>
void Function(const unsigned short(&args)[N])
{
    // use N
}

这适用于C ++ 03。数组需要是const,否则你不能传递这样的临时初始化列表。如果您需要修改函数内的元素,则需要复制。

答案 2 :(得分:2)

使用默认参数。

Function(int argc, unsigned short *args[], int a = 2, int b = 3, int c = 4) ;

或您想要的任何类型。默认值以及此示例中的最后三个不需要传递给函数。你可以这样调用这个函数..

Function (argc, args, 5, 4, 3) ;  //have to remember the maximum no. of parameters

我不知道你为什么要在你的程序中做这种事情。如果您不需要额外的变量,为什么要将它们包含在您的程序中? 但是

答案 3 :(得分:1)

要在C中编写类似的函数,您需要va_list和其他宏。这源于从C到装配的转换。在汇编中,您可以“查找”堆栈帧以查看传递给函数的更多参数。

但是,在C中,必须使用va_list类型和宏来完成此操作,因为在维护函数原型(参数的数量和类型)的同时,您可以使用其他内置机制。

请参阅http://www.gnu.org/software/libc/manual/html_node/Variadic-Functions.html

答案 4 :(得分:1)

这是两个标准的C ++解决方案。两者都需要支持C ++ 11的编译器:

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <utility>

template <typename T, typename... Us>
struct first_of_helper {
    typedef T type;
};

template <typename... Ts>
using FirstOf = typename first_of_helper<Ts...>::type;

template <typename... Ts>
void f(Ts&&... args) {
    typedef FirstOf<Ts...> T;
    std::vector<T> v_args{std::forward<Ts>(args)...};
    std::copy(v_args.begin(), v_args.end(), std::ostream_iterator<T>(std::cout, " "));
    std::cout << "\n";
}

template <typename T>
void g(std::initializer_list<T> args) {
    std::copy(args.begin(), args.end(), std::ostream_iterator<T>(std::cout, " "));
    std::cout << "\n";
}

int main() {
    f(1, 2, 3, 4);
    g({1, 2, 3, 4});
}

在C ++ 11之前,唯一可移植的解决方案是通过va_args。考虑一下:如果因为你可以编写更简单的代码而不需要va_args,为什么它会首先存在?

答案 5 :(得分:0)

在C ++中基本上有两种方法可以做变量参数:

  1. 从C继承的varargs语法,它使用va_list等。

  2. 创建容器以传入参数。此容器可以是数组,std :: vector,std :: list等。

  3. 通过直接传递参数并允许编译器构造容器,您提出的解决方案是非常Java的。这就是Sun / Oracle决定在Java 5中实现var-args的方式,并且已经证明是一个非常方便的功能。不幸的是,C ++不支持这种语法。