2016-02-17 2 views
-3

У меня есть char * [] [], и мне нужно его опорожнить и делать что-то новое время от времени, но я не знаю, как его повторно инициализировать и сновакак объявить char * [20] [250]

я попытался

args = malloc(sizeof(char*[20][250])*20); 

и

args = malloc(sizeof(char***)*20); 

, но я до сих пор не могу reinitilize массив. Является ли массив действительно 20 X 250 с символом char * как элемент?

и как вы выполняете итерацию по массиву символов, который относится к типу * [20] [250]?

это для execv и будет использоваться как этот

for(int i =0 ;i< maxArgs;i++){ 
    execv(args[i][0],args[i]); 
    ERROR("failed to start"); 
} 
+1

Downvoted, потому что вопрос не содержит [mcve] ,В результате я не знаю точно, что вы пытаетесь сделать, и ответы пытаются угадать, каков ваш предполагаемый тип данных. – user694733

+0

В заголовке очень ясно, что мой тип данных char * [] [] более конкретно char * [20] [250]. Я хочу инициализировать его, а затем повторно инициализировать его. и у него нет примера, потому что он понятия не имеет, как это сделать. –

+0

Указатели традиционно для начинающих. Неясно, поняли ли вы то, что хотите. Из ответов вы можете видеть, что у них разные идеи о том, что вам нужно делать. Хороший вопрос будет иметь короткий пример использования этой переменной после выделения, чтобы продемонстрировать, что вам действительно нужно. – user694733

ответ

3

Если args объявлен как:

char* args[20][250]; 

Вы можете выделить память для каждого элемента этого массива с помощью:

for (int i = 0; i < 20; ++i) 
{ 
    for (int j = 0; j < 250; ++j) 
    { 
     args[i][j] = malloc(sizeof(*args[i][j])*(SIZE_OF_STRING+1)); 
    } 
} 

Если args объявлено как:

char*** args; 

Необходимо еще несколько malloc звонков.

Шаг 1

Выделение памяти для arg.

args = malloc(sizeof(*args)*20); 

Шаг 2

Выделение памяти для args[0] - args[19].

for (int i = 0; i < 20; ++i) 
{ 
    args[i] = malloc(sizeof(*args[i])*250); 
} 

Шаг 3

Выделение памяти для args[0][0] - args[19][249].

for (int i = 0; i < 20; ++i) 
{ 
    for (int j = 0; j < 250; ++j) 
    { 
     args[i][j] = malloc(sizeof(*args[i][j])*(SIZE_OF_STRING+1)); 
    } 
} 

комбинат им

args = malloc(sizeof(*args)*20); 
for (int i = 0; i < 20; ++i) 
{ 
    args[i] = malloc(sizeof(*args[i])*250); 
    for (int j = 0; j < 250; ++j) 
    { 
     args[i][j] = malloc(sizeof(*args[i][j])*(SIZE_OF_STRING+1)); 
    } 
} 
+1

SIZE_OF_STRING + 1 при условии, что он содержит регулярную строку c. – Massey101

+0

SWEET это потрясающая благодарность! –

2

Просто чтобы быть ясно, когда вы желаете 2D массив типа char*[20][250], что вы просите в C-говорить 20-элементный массив char*[250] s, каждый из которых представляет собой 250-элементный массив из char * C-строк (каждый из которых представляет собой массив из char s).

Поскольку динамически выделенный 2D-массив не является областью памяти, а представляет собой массив указателей на другие массивы, вы не можете сделать это за один шаг. .Распределение, что будет делать то, что вы хотите, будет выглядеть следующим образом:

char ***args; 

args = malloc(sizeof(char**[20])); 
for (int i = 0; i < 20; ++i) { 
    args[i] = malloc(sizeof(char*[250])); 

    // optional, depending on your usage: 
    for (int j = 0; j < 20; ++j) 
     args[i][j] = ""; // This makes every `char *` element point to the same location in memory— the location of the compiled-in `""`/`(char *){ '\0' }`. 
} 

Чтобы освободить память, структура ваших звонков так же, как malloc -ную кода, но в обратном порядке: иерархическая

for (int i = 0; i < 20; ++i) 
    free(args[i]); 
free(args); 

Хорошо, поэтому технически можно выделить его как один большой блок, а затем подключить 20-элементный массив, чтобы указать на нужные смещения в blob. Это свершится, хотя и, как правило, не является необходимым - для большинства случаев использования прирост производительности был бы незначительным (и вам все равно потребуется malloc() отдельный массив указателей, которые адресуются в 2D-блок). Обычно вы видите только распределение 2D-blob, когда данные массово 2D - такие как данные изображения - и data[x][y] - синтаксис доступа исключен в пользу синтаксиса data[y * width + x], поскольку он не менее эффективен, чем то, что сделает компилятор, и не требует более одного malloc/free пара на каждый блок данных.

+0

Итак, если я объявляю 'int a [20] [250]', вы говорите мне, что это не один непрерывный блок памяти? – pat

+0

@pat Просто добавил сноску о том, что именно. Вы правы, это не так. C не имеет истинной двумерной поддержки массива; он имеет поддержку только массива-указателей на что-либо еще. –

+1

Прошу отличить. – pat

4

Postfix операторы всегда выше приоритет, чем префикс, поэтому, когда вы говорите

char*[20][250] 

вы получите массив из 20 массивов 250 указателей на символы. Вы можете использовать скобки привязки более * плотно:

char (*)[20][250] 

обозначает указатель на массив из 20 массивов 250 символов. Так что если у вас есть

char (*args)[20][250]; 

вы можете использовать

args = malloc(sizeof(char [20][250])); 
+0

Интересный стиль: 'malloc (sizeof (char [20] [250]))' – chux

+1

@chux Это форма, которую вы использовали бы, если бы вы хотели, чтобы выделенная память была в виде массива размером 20 × 250 2D одиночного -'char's, как говорит Крис с помощью _ "обозначает указатель на массив из 20 массивов из 250 символов" _. Если вам понадобится 20-битный 2D-массив C-строк, я не верю, что один 'malloc()' будет работать. –

+1

@chux: Я предпочитаю 'malloc (sizeof * args)', но я не думаю, что это то, о чем вы говорите. Тем не менее, явное текстовое приложение, о котором я могу думать, которое может соответствовать этому типу данных, будет терминальным эмулятором/редактором/экраном, и даже там unicode изменил большинство старых определений. – rici

1

Вы можете объявить ЬурейеЕ для 2d массива следующим образом:

typedef char *array2d_t[20][250]; 

Вы можете теперь malloc достаточно памяти для хранения одного экземпляр этого 2-го массива:

array2d_t *array3d = malloc(1 * sizeof(*array3d)); 

Поскольку указатели ведут себя как массивы вещей, на которые они указывают, у нас фактически есть 3d-массив, у первого измерения которого есть arity 1 (обратите внимание на 1 * в malloc), поэтому первый индекс может быть только 0. Мы можем его индексировать таким образом :

array3d[0][0][0] = "Hello"; 
    array3d[0][1][0] = "World"; 
    array3d[0][19][249] = "End of the world!"; 

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

(*array3d)[0][0] = "Hello"; 
    (*array3d)[1][0] = "World"; 
    (*array3d)[19][249] = "End of the world!"; 

в качестве альтернативы, мы можем объявить ЬурейеЕ для 1d массива следующим образом:

typedef char *array1d_t[250]; 

теперь malloc достаточно памяти для хранения 20 экземпляров этого 1d массива:

array1d_t *array2d = malloc(20 * sizeof(*array2d)); 

Мы не можем в настоящее время индекс массива с:

array2d[0][0] = "Hello"; 
    array2d[1][0] = "World"; 
    array2d[19][249] = "End of the world!"; 
+1

Typedefs ... Я не думал, что это будет работать так +1. Это все еще ограничивает размер массива размером, определяемым во время компиляции, но это вне области действия, о которой спрашивает OP. –

+0

Typedefs не нужны, но они упрощают понимание. Число измерений должно быть фиксированным, и все измерения, кроме первого, должны быть постоянными, чтобы компилятор выполнял вычисления адреса. Если вы готовы написать вычисление адресов вручную, вы можете иметь динамическое число размеров с динамическим размером и все еще иметь все элементы, которые остаются смежными. – pat

Смежные вопросы