Вы используете указатели.
В частности, вы используете указатель на адрес и, используя стандартные вызовы функций библиотеки C, вы просите операционную систему расширить кучу, чтобы вы могли хранить то, что вам нужно.
Теперь он может отказать, с чем вам нужно будет справиться.
Возникает следующий вопрос: как запросить двумерный массив? Ну, вы запрашиваете массив указателей, а затем расширяете каждый указатель.
В качестве примера рассмотрим следующее:
int i = 0;
char** words;
words = malloc((num_words)*sizeof(char*));
if ( words == NULL )
{
/* we have a problem */
printf("Error: out of memory.\n");
return;
}
for ( i=0; i<num_words; i++ )
{
words[i] = malloc((word_size+1)*sizeof(char));
if ( words[i] == NULL )
{
/* problem */
break;
}
}
if ( i != num_words )
{
/* it didn't allocate */
}
Это дает вам двумерный массив, где каждый элемент words[i]
может иметь разный размер, определяемый во время выполнения, как и количество слов.
Вам нужно будет free()
всю результирующую память, перебирая массив, когда вы закончите с ним:
for ( i = 0; i < num_words; i++ )
{
free(words[i]);
}
free(words);
Если вы этого не сделаете, вы создадите утечку памяти.
Вы также можете использовать calloc
. Разница заключается в соглашении о вызовах и эффекте - calloc
инициализирует всю память до 0
, а malloc
- нет.
Если вам нужно изменить размер во время выполнения, используйте realloc
.
Кроме того, важно, обратите внимание на word_size+1, который я использовал. Строки в C заканчиваются нулем, и это требует дополнительного символа, который вам нужно учитывать. Чтобы убедиться, что я это помню, я обычно устанавливаю размер переменной word_size
таким, каким должен быть размер слова (длина строки, как я ожидаю) и явно оставляю +1 в malloc вместо нуля. Тогда я знаю, что выделенный буфер может принять строку из word_size
символов. Не делать этого тоже нормально — я просто делаю это, потому что мне нравится явно учитывать ноль очевидным образом.
У этого подхода есть и обратная сторона — недавно я явно заметил, что это ошибка в доставке. Заметьте, я написал (word_size+1)*sizeof(type)
— представьте, однако, что я написал word_size*sizeof(type)+1
. Для sizeof(type)=1
это одно и то же, но Windows очень часто использует wchar_t
— и в этом случае вы зарезервируете один байт для своего последнего нуля, а не два — и это элементы типа type
, заканчивающиеся нулем, а не одиночные нулевые байты. Это означает, что вы будете перегружены чтением и записью.
Приложение: делайте это так, как вам нравится, просто следите за этими нулевыми терминаторами, если вы собираетесь передать буфер чему-то, что на них полагается.
person
Community
schedule
09.01.2011