英文:
How to convert variadic arguments to array in C
问题
以下是您要翻译的代码部分:
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;
}
char *output;
int retval;
run_command2(&output, &retval, "find", "/tmp", "-type", "f", NULL);
请注意,这些是您提供的代码片段的翻译。
英文:
For a project of mine, I created a function to run external commands (reduced to what's important for my question):
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);
}
...
}
The function is called like this:
char *output;
int retval;
const char *command = "find";
const char* const args[] = { command, "/tmp", "-type", "f", NULL };
run_command(&output, &retval, command, args);
Now, I created a wrapper that uses variadic arguments instead of an array of arguments:
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;
}
EDIT: note on do-while loop:<br/>
For the last element, this will result in fprintf(stderr, "Argument %i: %s\n", i, NULL)
, which is valid on GCC and will print '(null)', but might be undefined on other compilers. Thanks to @GiovanniCerretani for pointing this out.
Which is called like this:
char *output;
int retval;
run_command2(&output, &retval, "find", "/tmp", "-type", "f", NULL);
The wrapper works fine (Linux/x64/GCC 9.2.0), but is this actually a valid way to convert variadic arguments to array? Or does this just work by accident?
The documentation on va_*
is thin, e.g. there's no hint if a string retrieved using va_arg()
remains valid when va_arg()
is called again or when calling va_end()
.
答案1
得分: 3
你正在做的将按预期工作。
对va_arg
的调用使您能够访问传递给函数的char *
参数。这些指针的值是传递给run_command2
的,这意味着它们的范围至少在调用函数中是有效的。
因此,即使在调用va_end
之后它们仍然有效。
英文:
What you are doing will work as expected.
The calls to va_arg
get you access to the char *
arguments that were passed to the function. The values of these pointers is what was passed to run_command2
meaning their scope is valid at least in the calling function.
So they are valid even after calling va_end
.
答案2
得分: 0
以下是要翻译的内容:
由于这个主题上没有太多可用的信息,我决定实现我能想到的所有可能的包装器变体,并将它们放在一个 Gist 中:链接
希望这对其他面临相同任务的人有所帮助。
英文:
As there's not much available on this topic, I decided to implement all possible wrapper variants I could think of and put them in a Gist: Link
Hopefully this helps others facing the same task.
答案3
得分: -2
这个args = (const char **) malloc(argc * sizeof(char*));
看起来很奇怪。我宁愿先分配char **args = malloc(sizeof(char*) * (argc));
,然后再分配args[i] = malloc(sizeof(char) * (strlen(val) + 1));
。
你需要分配char **
,然后为该数组中的每个字符串分配内存。
英文:
This args = (const char **) malloc(argc * sizeof(char*));
is quite strange. I would rather first allocate char **args = malloc(sizeof(char*) * (argc));
and then args[i] = malloc(sizeof(char) * (strlen(val) + 1));
You need to allocate the char **
and then allocate each string in this array.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论