Как выделить массив перед вызовом strcpy? - PullRequest
7 голосов
/ 12 сентября 2010

Дано:

char test[] = "bla-bla-bla";

Какой из этих двух вариантов более правильный?

char *test1 = malloc(strlen(test));
strcpy(test1, test);

или

char *test1 = malloc(sizeof(test));
strcpy(test1, test);

Ответы [ 8 ]

24 голосов
/ 12 сентября 2010

Это будет работать для всех строк с нулевым символом в конце, включая указатели на char массивы:

char test[] = "bla-bla-bla";
char *test1 = malloc(strlen(test) + 1);
strcpy(test1, test);

Вы не получите правильный размер массива, на который указывает char* или const char* с sizeof. Поэтому это решение является более универсальным.

3 голосов
/ 12 сентября 2010

Вы должны использовать strlen, потому что sizeof не будет работать молча, если вы измените тест на строку, определенную во время выполнения.Это означает, что strlen является гораздо более безопасной идеей, чем sizeof, поскольку она будет продолжать работать.

3 голосов
/ 12 сентября 2010

Ни то, ни другое:

#include <string.h>
char *mine = strdup(test);
2 голосов
/ 12 сентября 2010

Я думаю, sizeof правильный.Причина в том, что strlen(str) даст вам длину строки (исключая завершающий ноль).И если вы используете strcpy, он на самом деле копирует всю строку, включая завершающий ноль, поэтому вы будете выделять на один байт меньше, если вы используете strlen в malloc.Но sizeof дает размер строки, указанной тестом, включая завершающий ноль, поэтому вы получите правильный размер malloc чанка для копирования строки, включая завершающий ноль.

2 голосов
/ 12 сентября 2010
char test[]="bla-bla-bla";
char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character
strcpy(test1, test);
1 голос
/ 12 сентября 2010

1) определенно вызывает UB

2) может вызывать UB (если malloc терпит неудачу)

Я бы пошел с 2), поскольку есть большая вероятность того, что конструкция работает какпредназначена;или даже лучше, я бы написал версию, которая работает как задумано (без UB) во всех ситуациях.


Редактировать

  • Не определеноПоведение в 1)

    test1 будет иметь место для символов в test, но не для завершающего '\0'.Вызов strcpy() попытается записать '\0' в память, которая не принадлежит test1, следовательно, UB.

  • Неопределенное поведение в 2)

    Если при вызове malloc() не удалось зарезервировать запрошенную память, test1 будет назначено NULL.Передача NULL в strcpy() вызывает UB.

Возвращаемое значение вызовов malloc()calloc() и друзьям) всегда должно быть проверено, чтобы убедиться, что операция работает какожидается.

0 голосов
/ 30 января 2014

Если это критический путь, sizeof имеет преимущество перед strlen, поскольку имеет сложность O (1), которая может экономить циклы ЦП.

0 голосов
/ 12 сентября 2010

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

С другой стороны, (2) предпочтительнее, если ваша строка на самом деле является массивом, так какв результате получается константа времени компиляции, а не вызов strlen (и, следовательно, более быстрый и меньший код).На самом деле современный компилятор, такой как gcc, может, вероятно, оптимизировать strlen, если он знает, что строка постоянна, но компилятору может быть сложно определить это, поэтому я всегда буду использовать sizeof, когда это возможно.*

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...