Фрагмент, который вы, видимо, имели в виду, — типичная ошибка:
char *f { char s = "hello"; return s; }
Коротко: это недопустимо — функция возвращает адрес локального автоматическогоавтоматическогоавтоматического массива, который перестаёт существовать при выходе из функции. Возвращаемый указатель становится «висячим» danglingdanglingdangling — дальнейшее обращение по нему даёт неопределённое поведение.
Почему так происходит
char s = "hello"; — s — автоматический массив, размещённый в стеке. Его время жизни ограничено временем выполнения функции.После return память стека может быть перезаписана при следующих вызовах; доступ по старому адресу может вернуть старые данные, мусор или привести к краху.
Пример, где это может «вроде бы работать», и где — рушиться:
Иногда программа продолжит выводить "hello" вотпочемуошибкаможетбытьнезаметнавот почему ошибка может быть незаметнавотпочемуошибкаможетбытьнезаметна.Иногда будет мусор, зависание или крах — поведение неопределённо.
2) Сделать массив статическим: char *fvoidvoidvoid { static char s = "hello"; return s; } Тогда s живёт всю программу; можно модифицировать. Но это не потокобезопасно и повторные вызовы делят один буфер.
3) Выделить память динамически callerобязаносвободитьcaller обязан освободитьcallerобязаносвободить:
include include
char fvoidvoidvoid { char s = malloc(strlen("hello") + 1); if !s!s!s return NULL; strcpy(s, "hello"); return s; }
5) Вернуть структуру с массивом вC99иновеевозможенвозвратмассивоподобногоstructв C99 и новее возможен возврат массивоподобного structвC99иновеевозможенвозвратмассивоподобногоstruct: typedef struct { char s666; } S; S fvoidvoidvoid { S r = { "hello" }; return r; }
Компиляторная помощь
Многие компиляторы предупреждают: «warning: function returns address of local variable». Обратите внимание на такие предупреждения.
Резюме Возвращать адрес локальной автоматическойавтоматическойавтоматической переменной нельзя — это неопределённое поведение. Используйте статическое хранение, динамическое выделение, возвращение литерала какconstchar∗как const char *какconstchar∗ или передачу буфера извне в зависимости от задачи.
Фрагмент, который вы, видимо, имели в виду, — типичная ошибка:
char *f {
char s = "hello";
return s;
}
Коротко: это недопустимо — функция возвращает адрес локального автоматическогоавтоматическогоавтоматического массива, который перестаёт существовать при выходе из функции. Возвращаемый указатель становится «висячим» danglingdanglingdangling — дальнейшее обращение по нему даёт неопределённое поведение.
Почему так происходит
char s = "hello"; — s — автоматический массив, размещённый в стеке. Его время жизни ограничено временем выполнения функции.После return память стека может быть перезаписана при следующих вызовах; доступ по старому адресу может вернуть старые данные, мусор или привести к краху.Пример, где это может «вроде бы работать», и где — рушиться:
Иногда программа продолжит выводить "hello" вотпочемуошибкаможетбытьнезаметнавот почему ошибка может быть незаметнавотпочемуошибкаможетбытьнезаметна.Иногда будет мусор, зависание или крах — поведение неопределённо.Безопасные альтернативы
1) Вернуть строковый литерал статическаядлительностьжизнистатическая длительность жизнистатическаядлительностьжизни:
const char *fvoidvoidvoid { return "hello"; }
Важно: модифицировать возвращённую строку нельзя undefinedbehaviorundefined behaviorundefinedbehavior.
2) Сделать массив статическим:
char *fvoidvoidvoid {
static char s = "hello";
return s;
}
Тогда s живёт всю программу; можно модифицировать. Но это не потокобезопасно и повторные вызовы делят один буфер.
3) Выделить память динамически callerобязаносвободитьcaller обязан освободитьcallerобязаносвободить:
include includechar fvoidvoidvoid {
char s = malloc(strlen("hello") + 1);
if !s!s!s return NULL;
strcpy(s, "hello");
return s;
}
4) Копировать в буфер, предоставленный вызывающим:
void fchar∗out,sizetoutlenchar *out, size_t outlenchar∗out,sizet outlen {
strncpy(out, "hello", outlen);
outoutlen−1outlen-1outlen−1 = '\0';
}
5) Вернуть структуру с массивом вC99иновеевозможенвозвратмассивоподобногоstructв C99 и новее возможен возврат массивоподобного structвC99иновеевозможенвозвратмассивоподобногоstruct:
typedef struct { char s666; } S;
S fvoidvoidvoid { S r = { "hello" }; return r; }
Компиляторная помощь
Многие компиляторы предупреждают: «warning: function returns address of local variable». Обратите внимание на такие предупреждения.Резюме
Возвращать адрес локальной автоматическойавтоматическойавтоматической переменной нельзя — это неопределённое поведение. Используйте статическое хранение, динамическое выделение, возвращение литерала какconstchar∗как const char *какconstchar∗ или передачу буфера извне в зависимости от задачи.