为了我的一个项目,我创建了一个运行外部命令的函数(只保留与我的问题相关的部分):
int run_command(char **output, int *retval, const char *command, const char* const args[])
{
...
pid_t pid = fork();
if (pid == 0) {
...
execvp(command, (char * const *)args);
}
...
}
这个函数的调用方式是这样的:
char *output;
int retval;
const char *command = "find";
const char* const args[] = { command, "/tmp", "-type", "f", NULL };
run_command(&output, &retval, command, args);
现在,我创建了一个使用可变参数而不是参数数组的包装器:
int run_command2(char **output, int *retval, const char *command, ...)
{
va_list val;
const char **args = NULL;
int argc;
int result;
// Determine number of variadic arguments
va_start(val, command);
argc = 2; // leading command + trailing NULL
while (va_arg(val, const char *) != NULL)
argc++;
va_end(val);
// Allocate args, put references to command / variadic arguments + NULL in args
args = (const char **) malloc(argc * sizeof(char*));
args[0] = command;
va_start(val, command);
int i = 0;
do {
fprintf(stderr, "Argument %i: %s\n", i, args[i]);
i++;
args[i] = va_arg(val, const char *);
} while (args[i] != NULL);
va_end(val);
// Run command, free args, return result
result = run_command(output, retval, command, args);
free(args);
return result;
}
编辑:do-while循环的说明:
对于最后一个元素,这将导致fprintf(stderr, "Argument %i: %s\n", i, NULL)
,在GCC上是有效的,并将打印“(null)”,但在其他编译器上可能未定义。感谢@GiovanniCerretani指出。
这样调用:
char *output;
int retval;
run_command2(&output, &retval, "find", "/tmp", "-type", "f", NULL);
这个包装器可以正常工作(Linux/x64/GCC 9.2.0),但这是否是将可变参数转换为数组的有效方法?还是仅仅是偶然起作用?
关于 va_* 的文档很少,例如没有提示当再次调用 va_arg() 或调用 va_end() 时,使用 va_arg() 检索的字符串是否仍然有效。
do/while
循环似乎有错误,由于你正在使用%s
打印一个NULL
指针,这应该是可以的。 - undefinedNULL
的部分,即将args
的最后一个元素设置为NULL
。 - undefinedargs
的最后一个元素是NULL。 - undefinedchar *args[argc] ; argv[0] = command ; ...
- undefined