英文:
Variable arguments in C
问题
有没有一种方法可以像读取argv[]
中的命令行参数一样读取/访问变量参数?
我知道有一种使用va_arg
的方法来做这件事,但只是想知道是否存在类似于"argv"的东西?
英文:
Is there a way to read/access variable arguments like we read command line arguments from argv[]
?
I'm aware of the va_arg
way of doing it but just wondering if something like "argv" exists for this?
答案1
得分: 2
C标准提供用于访问可变参数的唯一方法是va_arg
方法。
一般情况下,除非对语言进行了某种严重的扩展,否则不可能存在任何形式的va_arg[i]
方法来访问可变参数,因为va_arg[i]
必须具有一个固定的类型,而可变参数可以具有任何完整的对象类型。
C实现可以通过将参数连续地组织到内存中来实现<stdarg.h>
的特性,然后您可以访问该内存,包括将其视为具有相同类型的所有可变参数的数组。然而,这样做的方式不仅不具备对其他C实现的可移植性,而且通常不会得到特定C实现的支持。
英文:
The only facility the C standard provides for accessing variable arguments is the va_arg
method.
In general, it would be impossible (barring some gross extension to the language) for there to be any sort of va_arg[i]
method of accessing variable arguments since va_arg[i]
must have one fixed type but variable arguments can have any complete object type.
A C implementation might implement the <stdarg.h>
features by organizing arguments into memory serially, and then it could be possible to access that memory yourself, including accessing it as an array of all the variable arguments have the same type. However, the means for doing so would not only not be portable to other C implementations but generally would not be supported by the specific C implementation.
答案2
得分: 1
实际上,是的有一种方法
...通过宏技巧。
#include <stdio.h>
// foo是一个宏,它将接受多个字符串并将它们传递给_foo
#define foo(...) _foo( sizeof((char *[]){__VA_ARGS__}) / sizeof(char *), (char *[]){__VA_ARGS__})
void _foo(int argc, char *argv[])
{
printf("argc: %d\n", argc);
for (int i = 0; i < argc; i++)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}
int main(void)
{
foo("Hello", "World");
}
工作原理
它使用:
...
和__VA_ARGS__
:宏中可变参数的语法(char *[]){/*...*/}
:创建字符串数组的复合字面量sizeof(array) / sizeof(elem)
:获取数组中元素的数量的技巧
宏foo
从可变参数中创建了两个数组。第一个数组用于大小技巧,并传递给argc
。第二个直接传递给argv
。
上面提到的两点已经在评论中由@Brian61354270和@Cubic指出,只是将整个过程放在一起。特别是@Cubic,他展示了相同的方法,但没有使用宏。
几个注意事项
- 与
va_arg
不同,这个技巧只能在具有相同类型的参数时使用。 - 这使用了一个宏。通常,这意味着宏参数可能会被多次评估。在这里,参数看起来像被评估两次,但
sizeof
不会评估。因此,调用foo(bar())
将只调用一次bar
。(这很好,这就是我们想要的) - 它的行为与
main
的argc
/argv
不完全相同。首先,我没有在argv的末尾放置NULL
。不过,这很容易添加。
英文:
Actually, yes there's a way
...with macro tricks.
#include <stdio.h>
// foo is a macro that'll take multiple strings and pass them to _foo
#define foo(...) _foo( sizeof((char *[]){__VA_ARGS__}) / sizeof(char *), (char *[]){__VA_ARGS__})
void _foo(int argc, char *argv[])
{
printf("argc: %d\n", argc);
for (int i = 0; i < argc; i++)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}
int main(void)
{
foo("Hello", "World");
}
How it works
It uses:
...
and__VA_ARGS__
: the syntax for variadic arguments in macros(char *[]){/*...*/}
: a compound literal to create a array of stringssizeof(array) / sizeof(elem)
: a trick to get the number of elements in an array
The macro foo
creates two arrays from the variadic parameters. The first array is used in the size trick, and passed to argc
. The second is directly passed to argv
.
Two of the above points have already been pointed out in the comments by @Brian61354270 and @Cubic, it was just a matter of putting the whole thing together. Especially @Cubic, who showed the same way but without a macro.
A few notes
- Unlike with
va_arg
, this technique can only be used when you have arguments of the same type. - This uses a macro. Often, it implies that the macro arguments might be evaluated multiple times. Here it looks like the arguments are evaluated twice, but sizeof doesn't evaluate. So calling
foo(bar())
will only callbar
once. (Which is pretty good, that's what we want) - It doesn't behave exactly like the
main
'sargc
/argv
. For starters, I didn't putNULL
at the end of argv. That's trivial to add though.
答案3
得分: 0
你可能在提到像printf
这样的函数,它可以在不同的时间接受不同类型的参数吗?
printf
是一个可变参数函数的示例,声明如下:
printf(char* format, ...);
这里的...
表示后续的参数可以是任何类型,且数量可以任意。
调用者使用类型va_list
以及在头文件<stdarg.h>
中定义的宏va_start
、va_arg
和va_end
来处理这些参数。
有很多在线示例可以解释如何使用它。
英文:
Are you perhaps referring to the way that functions like printf
can take different arguments at different times?
printf
is an example of a variadic function, and is declared as:
printf(char* format, ...);
Where the ...
means the following arguments can be of any type, and there can be any number of them.
These are processed by the caller using type va_list
and macros va_start
, va_arg
and va_end
, all defined in header file <stdarg.h>
.
There are plenty of examples online that explain how this is used.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论