По сути, да, это безопасно в том смысле, что значение будет длиться бесконечно, потому что оно статично.
Это небезопасно в том смысле, что вы вернули постоянный указатель на переменные данные, а не переменный указатель на постоянные данные. Лучше, если вызывающим функциям не разрешено изменять данные:
const char *GetString(void)
{
static char sTest[5];
strncpy(sTest, "Test", sizeof(sTest)-1);
sTest[sizeof(sTest)-1] = '\0';
return sTest;
}
В показанном простом случае вряд ли стоит беспокоиться о переполнении буфера, хотя моя версия кода действительно беспокоится и гарантирует нулевое завершение. Альтернативой может быть использование функции TR24731 strcpy_s
вместо:
const char *GetString(void)
{
static char sTest[5];
strcpy_s(sTest, sizeof(sTest), "Test");
return sTest;
}
Что еще более важно, оба варианта возвращают (переменный) указатель на постоянные данные, поэтому пользователь не должен модифицировать строку и (вероятно) вытаптывать за пределы диапазона массива. (Как указывает @strager в комментариях, возвращение const char *
не является гарантией того, что пользователь не будет пытаться изменить возвращенные данные. Однако ему необходимо привести приведенный указатель, чтобы он не был константным, а затем изменить данные, это вызывает неопределенное поведение, и в этот момент возможно все.)
Одним из преимуществ буквального возврата является то, что обещание не писать обычно может быть применено компилятором и операционной системой. Строка будет помещена в текстовый (программный) сегмент программы, и операционная система создаст ошибку (нарушение сегментации в Unix), если пользователь попытается изменить данные, на которые указывает возвращаемое значение.
[По крайней мере, один из других ответов отмечает, что код не является повторным входом; это правильно. Версия, возвращающая литерал, является вновь поступающей. Если важен повторный вход, интерфейс должен быть исправлен так, чтобы вызывающая сторона предоставляла место, где хранятся данные.]