如何将 **argv 复制到新变量?
How to copy **argv to a new variable?
我想使用像 memcpy 这样的东西来复制一个变量,例如 char **argv
,但是怎么做呢?我可以知道大小以及如何对其进行参数化吗,因为 memcpy
不将两星作为参数。我必须写一个循环吗?
我必须在执行之前建立管道。因此,我想在循环的每次迭代中使用 "spawn" 变量,例如 argv
。
token = strtok(cmd, "|");
i = 0;
while (token != NULL)
{
printf("token %s\n", token);
makeArgs(token, &argc, &argv);
for (int b = 0; b < argc; b++) {
printf("makeargs %d: %s\n", b, argv[b]);
}
// Will copy argc characters from array1 to array2
/* memcpy(makearg,argc, argc*18*sizeof(int));*/
shellcommand[i].argv = argv;
i++;
token = strtok(NULL, "|");
}
/* do stuff */
fork_pipes(argc, shellcommand);
我的目标是建立如下管道。
/* who | awk '{print }' | sort | uniq -c | sort -n */
static char *cmd0[] = { "who", 0 };
static char *cmd1[] = { "awk", "{print }", 0 };
static char *cmd2[] = { "sort", 0 };
static char *cmd3[] = { "uniq", "-c", 0 };
static char *cmd4[] = { "sort", "-n", 0 };
static char **cmds[] = { cmd0, cmd1, cmd2, cmd3, cmd4 };
此代码对 argv
进行了深度复制:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char** argv)
{
// allocate memory and copy strings
char** new_argv = malloc((argc+1) * sizeof *new_argv);
for(int i = 0; i < argc; ++i)
{
size_t length = strlen(argv[i])+1;
new_argv[i] = malloc(length);
memcpy(new_argv[i], argv[i], length);
}
new_argv[argc] = NULL;
// do operations on new_argv
for(int i = 0; i < argc; ++i)
{
printf("%s\n", new_argv[i]);
}
// free memory
for(int i = 0; i < argc; ++i)
{
free(new_argv[i]);
}
free(new_argv);
}
感谢@milleniumbug 的指针,我制作了一个 returns 只有一个指针的版本,因此更容易跨越实例或线程边界传递,也更容易在使用后释放。没有你的提示,我不会有线程安全的方法。
char **copy_argv(int argc, char *argv[]) {
// calculate the contiguous argv buffer size
int length=0;
for(int i = 0; i < argc; i++)
{
length += (strlen(argv[i]) + 1);
}
char** new_argv = (char**)malloc((argc + 1) * sizeof(char*) + length);
// copy argv into the contiguous buffer
length = 0;
for (int i = 0; i < argc; i++)
{
new_argv[i] = &(((char*)new_argv)[argc * sizeof(char*) + length]);
strcpy(new_argv[i], argv[i]);
length = (strlen(argv[i]) + 1);
}
new_argv[argc] = NULL;
return(new_argv);
}
我猜这个单一的指针结构是不可变的,而且更容易复制。
我喜欢@conrad-b 的解决方案,因为它将内存布置在一个连续的块中。但是,它有几个错误。
new_argv[i] = &(((char*)new_argv)[argc * sizeof(char*) + length]);
将开始写入 argv[0] 数据,稍后将写入终止 NULL ptr。所以 new_argv[0] 的前 4 或 8 个字节将被清零。
length = (strlen(argv[i]) + 1);
应该是 += 操作。
所以最终的解决方案应该更像这样:
char **copy_argv(int argc, char *argv[]) {
// calculate the contiguous argv buffer size
int length=0;
size_t ptr_args = argc + 1;
for (int i = 0; i < argc; i++)
{
length += (strlen(argv[i]) + 1);
}
char** new_argv = (char**)malloc((ptr_args) * sizeof(char*) + length);
// copy argv into the contiguous buffer
length = 0;
for (int i = 0; i < argc; i++)
{
new_argv[i] = &(((char*)new_argv)[(ptr_args * sizeof(char*)) + length]);
strcpy(new_argv[i], argv[i]);
length += (strlen(argv[i]) + 1);
}
// insert NULL terminating ptr at the end of the ptr array
new_argv[ptr_args-1] = NULL;
return (new_argv);
}
我想使用像 memcpy 这样的东西来复制一个变量,例如 char **argv
,但是怎么做呢?我可以知道大小以及如何对其进行参数化吗,因为 memcpy
不将两星作为参数。我必须写一个循环吗?
我必须在执行之前建立管道。因此,我想在循环的每次迭代中使用 "spawn" 变量,例如 argv
。
token = strtok(cmd, "|");
i = 0;
while (token != NULL)
{
printf("token %s\n", token);
makeArgs(token, &argc, &argv);
for (int b = 0; b < argc; b++) {
printf("makeargs %d: %s\n", b, argv[b]);
}
// Will copy argc characters from array1 to array2
/* memcpy(makearg,argc, argc*18*sizeof(int));*/
shellcommand[i].argv = argv;
i++;
token = strtok(NULL, "|");
}
/* do stuff */
fork_pipes(argc, shellcommand);
我的目标是建立如下管道。
/* who | awk '{print }' | sort | uniq -c | sort -n */
static char *cmd0[] = { "who", 0 };
static char *cmd1[] = { "awk", "{print }", 0 };
static char *cmd2[] = { "sort", 0 };
static char *cmd3[] = { "uniq", "-c", 0 };
static char *cmd4[] = { "sort", "-n", 0 };
static char **cmds[] = { cmd0, cmd1, cmd2, cmd3, cmd4 };
此代码对 argv
进行了深度复制:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char** argv)
{
// allocate memory and copy strings
char** new_argv = malloc((argc+1) * sizeof *new_argv);
for(int i = 0; i < argc; ++i)
{
size_t length = strlen(argv[i])+1;
new_argv[i] = malloc(length);
memcpy(new_argv[i], argv[i], length);
}
new_argv[argc] = NULL;
// do operations on new_argv
for(int i = 0; i < argc; ++i)
{
printf("%s\n", new_argv[i]);
}
// free memory
for(int i = 0; i < argc; ++i)
{
free(new_argv[i]);
}
free(new_argv);
}
感谢@milleniumbug 的指针,我制作了一个 returns 只有一个指针的版本,因此更容易跨越实例或线程边界传递,也更容易在使用后释放。没有你的提示,我不会有线程安全的方法。
char **copy_argv(int argc, char *argv[]) {
// calculate the contiguous argv buffer size
int length=0;
for(int i = 0; i < argc; i++)
{
length += (strlen(argv[i]) + 1);
}
char** new_argv = (char**)malloc((argc + 1) * sizeof(char*) + length);
// copy argv into the contiguous buffer
length = 0;
for (int i = 0; i < argc; i++)
{
new_argv[i] = &(((char*)new_argv)[argc * sizeof(char*) + length]);
strcpy(new_argv[i], argv[i]);
length = (strlen(argv[i]) + 1);
}
new_argv[argc] = NULL;
return(new_argv);
}
我猜这个单一的指针结构是不可变的,而且更容易复制。
我喜欢@conrad-b 的解决方案,因为它将内存布置在一个连续的块中。但是,它有几个错误。
new_argv[i] = &(((char*)new_argv)[argc * sizeof(char*) + length]);
将开始写入 argv[0] 数据,稍后将写入终止 NULL ptr。所以 new_argv[0] 的前 4 或 8 个字节将被清零。length = (strlen(argv[i]) + 1);
应该是 += 操作。
所以最终的解决方案应该更像这样:
char **copy_argv(int argc, char *argv[]) {
// calculate the contiguous argv buffer size
int length=0;
size_t ptr_args = argc + 1;
for (int i = 0; i < argc; i++)
{
length += (strlen(argv[i]) + 1);
}
char** new_argv = (char**)malloc((ptr_args) * sizeof(char*) + length);
// copy argv into the contiguous buffer
length = 0;
for (int i = 0; i < argc; i++)
{
new_argv[i] = &(((char*)new_argv)[(ptr_args * sizeof(char*)) + length]);
strcpy(new_argv[i], argv[i]);
length += (strlen(argv[i]) + 1);
}
// insert NULL terminating ptr at the end of the ptr array
new_argv[ptr_args-1] = NULL;
return (new_argv);
}