что отличается между инициализацией строки и использованием strdup () - PullRequest
0 голосов
/ 17 января 2020

В чем разница между

char *key_str="kiwi";

и

char *key_str = strdup("kiwi");

Например:

int strCmp(void *vp1, void *vp2) {
    char * s1 = (char *) vp1;
    char * s2 = (char *) vp2;
    return strcmp(s1, s2);
}

Почему эти *key_str ведут себя по-разному при использовании в функция strCmp()?

ср c код: https://github.com/alexparkjw/typing/blob/master/pa2.c

1 Ответ

5 голосов
/ 17 января 2020

В C все строковые литералы на самом деле являются массивами (эффективно только для чтения) символов.

С

char *str = "kiwi";

вы указываете str на первый элемент такого массив.

Это несколько эквивалентно

char internal_array_for_kiwi[5] = { 'k', 'i', 'w', 'i', '\0' };
char *str = &internal_array_for_kiwi[0];

Функция strdup динамически распределяет память и копирует переданную строку в эту память, создавая копию строки.

Таким образом, после

char *str = strdup("kiwi");

у вас будет два массива, содержащих одинаковое содержимое.

Это эквивалентно

char internal_array_for_kiwi[5] = { 'k', 'i', 'w', 'i', '\0' };
char *str = malloc(strlen(internal_array_for_kiwi) + 1);
strcpy(str, internal_array_for_kiwi);

Необходимо подчеркнуть важное различие между ними: буквенные строки в C не могут быть изменены. Попытка изменить такую ​​строку приведет к неопределенному поведению . Массивы не const, но фактически доступны только для чтения.

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

Так что, если у нас есть

char *str1 = "kiwi";
char *str2 = strdup("kiwi");

, тогда

str1[0] = 'l';  // Undefined behavior, attempting to modify a literal string
str2[0] = 'l';  // Valid, strdup returns memory you can modify

Потому что буквально Строки не могут быть изменены, рекомендуется использовать const char * при указании на них:

const char *str1 = "kiwi";

Еще одна важная вещь, которую следует помнить: так как strdup выделяет память динамически (используя malloc), вам нужно free этой памяти, как только вы закончите со строкой:

free(str2);

Если вы не освободите память, у вас будет утечка памяти.


Beyond выше, нет никакой эффективной разницы между этими двумя вариантами. Оба могут использоваться взаимозаменяемо при вызове функций, например.

...