Создать массив Char * динамически в C - PullRequest
0 голосов
/ 07 октября 2019

Я пытаюсь создать массив char * динамически для execv. Количество параметров известно только во время выполнения. Это мой код:

char *id_array= malloc((size_array) * sizeof(char));
int length = 4 + groupId_list.nr; //groupId_list.nr know only at runtime
id_array= realloc(id_array,sizeof(char)*length);

id_array[0] = "/usr/bin/java";
id_array[1] = "-jar";
id_array[2] = "pathToFile/jar";

for (int j = 0; j < groupId_list.nr; j++) {
    id_array[j+3] = groupId_list.items[j].string;
}
id_array[size_array-1] = (char*)0; //terminator need for execv

execv("/usr/bin/java",&id_array);

Когда я компилирую код, у меня появляются разные предупреждения:

warning: incompatible pointer to integer conversion assigning to 'char' from 'char [14]'
 id_array[0] = "/usr/bin/java";
warning: incompatible pointer to integer conversion assigning to 'char' from 'char [5]'
 id_array[1] = "-jar";
....

Я пытался следовать различным учебникам, но я не понимал, как я могу решитьЭто. Спасибо.

Ответы [ 2 ]

2 голосов
/ 07 октября 2019

Вам нужен массив строк, массив массивов символов, указатель на указатель на символ.

int length = 4 + groupId_list.nr;
char **id_array= malloc(sizeof(char*) * length);

const char *str1 = "/usr/bin/java";
id_array[0] =  malloc(sizeof(char) * (strlen(str1) + 1));
strcpy(id_array[0], str1);

const char *str2 = "-jar";
id_array[1] =  malloc(sizeof(char) * (strlen(str2) + 1));
strcpy(id_array[1], str2);

const char *str3 = "pathToFile/jar";
id_array[2] =  malloc(sizeof(char) * (strlen(str3) + 1));
strcpy(id_array[2], str3);

for (size_t j = 0; j < groupId_list.nr; ++j) {
    id_array[j + 3] = malloc(sizeof(char) * (strlen(groupId_list.items[j].string) + 1));
    strcpy(id_array[j + 3], groupId_list.items[j].string);
}

id_array[length - 1] = NULL;

Это становится понятнее, когда вы используете sizeof(*variable), что намного удобнее для чтенияи менее подвержен ошибкам, и более понятен. Также детали const char *string = "some string"; malloc(strlen(string) + 1); strcpy можно упростить, просто позвонив по номеру strdup.

char **id_array= malloc(sizeof(*id_array) * 4);
id_array[0] = strdup("/usr/bin/java");
id_array[1] = strdup("-jar");
id_array[2] = strdup("pathToFile/jar");
for (int j = 0; j < groupId_list.nr; j++) {
    id_array[j + 3] = strdup(groupId_list.items[j].string);
}
id_array[length - 1] = NULL;

Не забудьте освободить память.

Или в зависимости от вашей памятимодель владения, может быть, вы не хотите дублировать память и просто назначать указатели. Затем просто выделите память для массива указателей на символ и назначьте указатели. Вы могли бы выделить память для строковых литералов в стеке.

char **id_array = malloc(sizeof(*id_array) * length);
id_array[0] = (char[]){"/usr/bin/java"};
id_array[1] = (char[]){"-jar"};
id_array[2] = (char[]){"pathToFile/jar"};
for (....) { 
   id_array[j + 3] = groupId_list.items[j].string;
}
id_array[length - 1] = NULL;

Или вы могли бы даже внимательно прочитать спецификацию execv (см. этот пост ) и передать указатели на строковые литералына execv и игнорируйте квалификатор const, так как execv не будет изменять массив в любом случае.

# string literals are constant
const char **id_array = malloc(sizeof(*id_array) * length);
id_array[0] = "/usr/bin/java";
id_array[1] = "-jar";
id_array[2] = "pathToFile/jar";
for (....) { 
   id_array[j + 3] = groupId_list.items[j].string;
}
id_array[length - 1] = NULL;

# explicitly remove the const qualifier, which is safe, because we 
# know from the documentation that execv will not modify the array contents
execv(...., (void*)id_array);
0 голосов
/ 07 октября 2019

Вы пытаетесь сохранить char * в char, вы должны использовать указатель указателя:

char **id_array = malloc((size_array) * sizeof(char *));

Строковые литералы const char[] (статический эквивалент const char *).

...