Посленазначая указатель, заданный malloc(3)
в a
, вы перезаписываете этот указатель адресом строкового литерала "OneExample"
.Это делает две вещи:
- Во-первых, вы теряете значение указателя, заданное
malloc(3)
и которое было сохранено в a
, поэтому у вас его больше нет, и вы никогда не сможетедо free(3)
этого.Это называется утечка памяти , и вам следует избегать их, поскольку они являются ошибками программирования. - Это приведет к некоторому неопределенному поведению при вызове
free(3)
, который принимает тольков качестве параметра значение указателя, ранее возвращаемое malloc
(и это не фактический адрес, сохраненный в a
). Возможно, вы получили некоторое прерывание SIGSEGV
, и ваша программа аварийно завершилась из-за этого вызова.
Когда вы делаете присвоение a
, вы просто изменяете значение указателя, которое вы там сохранили, а не содержимое отложенной памяти, так что именно это имеет смысл при вызове strcpy(3)
, потому что этоозначает только скопировать строку символов вокруг.Или вы можете копировать символы один за другим, как в:
char *a = malloc(5); /* this makes a memory buffer of 5 char available through a */
int i;
for(i = 0; i < 4 /* see below */; i++)
a[i] = "OneExample"[i]; /* this is the copy of the char at pos i */
a[i] = '\0'; /* we must terminate the string if we want to print it */
последний шаг - это то, что делает необходимым запуск цикла for
в то время как i < 4
, а не в то время как i < 5
, так какмы запросили у malloc()
пять символов, и это должно включать символ конца строки.
Существует одна стандартная альтернатива этой библиотеке:
char *a = strdup("OneExample");
, что эквивалентно:
#define S "OneExample"
char *a = malloc(strlen(S) + 1); /* see the +1 to allow for the null terminator */
strcpy(a, S);
но если вы хотите решить свой пример с усечением строки в 5, вы можете сделать следующее:
char *dup_truncated_at(const char *s, int at)
{
char *result = malloc(at + 1); /* the size we need */
memcpy(result, s, at); /* copy the first at chars to the position returned by malloc() */
result[at] = '\0'; /* and put the string terminator */
return result; /* return the pointer, that must be freed with free() */
}
и вы сможете вызвать егокак:
char *a = dup_truncated_at("OneExample", 5);
printf("truncated %s\n", a);
free(a); /* remember, the value returned from dup_truncated_at has been obtained with a call to malloc() */