5

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

首先:我不是在寻找 va_list 和其他宏。我正在寻找的是类似于 main-function 参数的东西。

众所周知,默认原型是:

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++,并寻找一种不同的方法来解决我的问题。

再次,非常感谢。

4

6 回答 6

3

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

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

这比 acientva_list函数类型更安全,因为它将列表中的所有表达式转换为unsigned short.

现代 C++ 现在VA_ARGS在宏预处理阶段也具有此功能。但我不知道您将如何创建一个临时向量,该向量将使用这些值进行初始化。

于 2012-10-07T18:36:23.730 回答
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,否则你不能像这样传递一个临时初始化列表。如果您需要修改函数内部的元素,则需要进行复制。

于 2012-10-07T18:39:02.463 回答
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

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

于 2012-10-07T18:27:25.400 回答
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 之前,唯一可移植的解决方案是 via va_args。考虑一下:如果va_args不需要因为您可以编写更简单的代码,那么它为什么会首先存在?

于 2012-10-07T19:22:56.897 回答
1

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

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

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

于 2012-10-07T18:34:24.390 回答
0

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

  1. 从 C 继承的可变参数语法使用 va_list 等。

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

您提出的通过直接传递参数并允许编译器构造容器的解决方案非常具有 Java 风格。这就是 Sun/Oracle 决定在 Java 5 中实现 var-args 的方式,结果证明这是一个非常方便的特性。不幸的是,C++ 不支持这种语法 afaik。

于 2012-10-07T18:36:36.097 回答