Выделение памяти для языка char * C

Это правильный способ выделения памяти для char *.

char* sides ="5";

char* tempSides;

tempSides = (char*)malloc(strlen(inSides) * sizeof(char));

person boom    schedule 04.06.2010    source источник
comment
@brickner, что насчет этого в strlen, strlen (inSides) + 1   -  person boom    schedule 04.06.2010


Ответы (7)


Почти. Строки заканчиваются NULL, поэтому вы, вероятно, захотите выделить дополнительный байт для хранения байта NULL. То есть, хотя sides имеет длину 1 символ, на самом деле это 2 байта: {_2 _, _ 3_}.

Так было бы:

tempSides = (char *)malloc((strlen(sides)+1)*sizeof(char));

и если вы хотите скопировать его в:

strcpy(tempSides, sides);
person Claudiu    schedule 04.06.2010
comment
Вы имеете в виду '\ 0', когда говорите NULL. '\ 0' - это NULL, а не NULL. - person George Phillips; 04.06.2010
comment
Обратите внимание, что умножение на sizeof(char) необязательно; sizeof(char) определяется как 1. - person caf; 04.06.2010
comment
@caf: Верно, но его отсутствие затрудняет адаптацию кода к wchar_t или TCHAR, когда это необходимо - если нет умножений, есть риск забыть его использовать. - person sharptooth; 04.06.2010
comment
Не забудьте проверить NULL перед strcpy - person R Samuel Klatchko; 04.06.2010
comment
@sharptooth: Умножение на sizeof *tempSides было бы лучше, если вы беспокоитесь о переходе на wchar_t позже. - person jamesdlin; 04.06.2010
comment
@ Джордж Филлипс: Строго говоря, вы имеете в виду «нулевой символ». nul - это прозвище ASCII для нулевого символа; термин «нуль» не встречается нигде в стандарте C. - person dreamlax; 04.06.2010
comment
@R Samuel Klatchko: как вы предлагаете провести такую ​​проверку и каковы будут возможные последствия? Если после ввода нет \0, и strlen(), и strcpy не пройдут так же, как и предложенная вами проверка. - person MSalters; 04.06.2010
comment
@MSalters: он имел в виду проверку возвращаемого значения malloc. - person jweyrich; 04.06.2010
comment
Я бы использовал strncpy вместо strcpy. В этом случае мы знаем, что буфер достаточно большой, поэтому strcpy в порядке. Однако я предпочитаю избегать strcpy во ВСЕХ случаях. Накладные расходы настолько малы, что вы вряд ли заметите реальную разницу в производительности. - person daotoad; 05.06.2010

Обратите внимание, что:

  1. Строки заканчиваются нулем (\ 0), и strlen () не учитывает их;
  2. По определению sizeof (char) равен 1 (байту), поэтому он не требуется;
  3. Если вы используете компилятор C (не C ++), нет необходимости приводить его к char *;

Итак, это было бы:

char *tempSides = malloc(strlen(inSides) + 1);

Тем не менее, если вы хотите продублировать содержимое inSides, вы можете использовать strdup, например:

char *tempSides = strdup(inSides);
if (tempSides != NULL) {
    // do whatever you want...
    free(tempSides);
}
person jweyrich    schedule 04.06.2010

Как уже указывалось, вы пропустили выделение места для завершающего символа NUL. Но я также хотел указать на пару вещей, которые могут сделать ваш код более лаконичным.

По определению sizeof(char) всегда равно 1, поэтому вы можете сократить строку выделения до:

tempSides = (char*)malloc(strlen(inSides) + 1);

Другое дело, что это похоже на то, что вы делаете дубликат строки. Есть встроенная функция, которая сделает это за вас:

tempSides = strdup(inSides);

Это обрабатывает получение длины, выделение правильного количества байтов и копирование данных.

person R Samuel Klatchko    schedule 04.06.2010

С этим проблема. tempSides будет указывать на неинициализированный блок памяти размером 1. Если вы намереваетесь скопировать строку сторон в tempSides, вам нужно будет выделить размер на один байт больше, чтобы сохранить нулевой ограничитель для строки. Значение, возвращаемое функцией strlen (), не включает нулевой терминатор в конце строки.

person Vagrant    schedule 04.06.2010

Нет, не совсем. Как уже отмечали другие, вам нужно выделить место для терминатора NUL.

Кроме того, обычно вам не следует использовать возврат от malloc. Это может скрыть ошибку, из-за которой вы забыли #include правильный заголовок. Умножение на sizeof(char) также бессмысленно, поскольку стандарты (как C, так и C ++) определяют sizeof(char) всегда равным 1.

Наконец, каждый вызов malloc должен включать проверку результата. Я бы обернул все это в функцию:

char *dupe_string(char const *string) { 
    char *temp;
    if (NULL!=(temp=malloc(strlen(string)+1)))
        strcpy(temp, string);
    return temp;
}
person Jerry Coffin    schedule 04.06.2010

Умножение количества элементов на sizeof(char) является делом личных предпочтений, поскольку sizeof(char) всегда равно 1. Однако, если вы делаете это для единообразия, лучше использовать тип указателя получателя для определения размера элемента вместо того, чтобы указывать тип явно. И не приводите результат malloc

tempSides = malloc(strlen(inSides) * sizeof *tempSides);

Конечно, при работе со строками с нулевым завершением вы должны помнить о выделении дополнительного места для завершающего нулевого символа. Невозможно сказать, намерены ли вы сделать tempSides строку с нулевым завершением в этом случае, поэтому я не могу сказать, нужно ли вам это.

person AnT    schedule 04.06.2010
comment
Ни за что? Ему лучше использовать строки с нулевым завершением при вызове _1 _... Если он использует свой собственный strlen, то я действительно не хочу быть программистом обслуживания после него. ;) - person Secure; 04.06.2010
comment
@Secure: это означает только, что inSides имеет нулевое завершение. В коде нет указаний на то, что tempSides также должен оканчиваться нулем. - person AnT; 04.06.2010

Правильный способ выделения динамической памяти для tempSides показан ниже:

char* sides ="5";
char* tempSides;
tempSides = (char*)malloc((strlen(sides) + 1) * sizeof(char));

char* хранит строковые данные, аналогичные char[]. Строки null (\0) завершаются. Таким образом, дополнительный один байт должен быть выделен для хранения null символов.

Динамически выделяемый блок памяти должен быть освобожден с помощью free() после его использования. Если не освободить, произойдет утечка памяти.

free(tempSides);

После освобождения памяти необходимо назначить NULL, чтобы он не был висящим указателем.

tempSides = NULL;
person pkthapa    schedule 16.11.2016