Ты абсолютно прав. Ваш массив c во втором примере размещается в стеке, и, следовательно, память будет сразу же использоваться повторно. В частности, если у вас был код типа
printf("%s\n",greet());
вы получите странные результаты, потому что вызов printf использовал бы часть пространства вашего массива.
Решение состоит в том, чтобы выделить память где-то еще. Для примера:
char c[] = "Hello";
char * greet() {
return c;
}
Будет работать. Другой вариант - статически распределить его по объему:
char * greet() {
static char c[] = "Hello";
return c;
}
потому что статическая память выделяется отдельно от стека в пространстве данных.
Ваш третий выбор - разместить его в куче через malloc:
char * greet() {
char * c = (char *) malloc(strlen("Hello")+1); /* +1 for the null */
strcpy(c, "Hello");
return c;
}
но теперь вы должны убедиться, что память каким-то образом освобождена, иначе у вас утечка памяти.
Обновление
Одна из тех вещей, которые кажутся более запутанными, чем я ожидаю, это то, что именно является "утечкой памяти". Утечка - это когда вы динамически распределяете память, но теряете адрес, поэтому ее нельзя освободить. Ни в одном из этих примеров не обязательно есть утечка, но только в третьем потенциально есть утечка, потому что она единственная, которая динамически распределяет память. Итак, предполагая третью реализацию, вы могли бы написать этот код:
{
/* stuff happens */
printf("%s\n", greet());
}
Это утечка; возвращается указатель на память malloc, printf
использует его, а затем теряется; Вы не можете освободить это больше. С другой стороны,
{
char * cp ;
/* stuff happens */
cp = greet();
printf("%s\n", cp);
free(cp);
}
не утечка, потому что указатель сохраняется в автоматической переменной cp
достаточно долго, чтобы вызвать free()
на нем. Теперь, несмотря на то, что cp исчезает, как только выполнение завершается, он завершает фигурную скобку, так как free был вызван, память восстанавливается и не протекает.