Подтвердить что ты не робот

Объем (струнных) литералов

Я всегда стараюсь не возвращать строковые литералы, потому что я боюсь, что они не определены вне функции. Но я не уверен, что это так. Возьмем, например, эту функцию:


const char *
return_a_string(void)
{
    return "blah";
}

Это правильный код? Он работает для меня, но, возможно, он работает только для моего компилятора (gcc). Итак, вопрос в том, имеют ли (string) литералы рамки или они присутствуют/определены все время.

4b9b3361

Ответ 1

Этот код отлично подходит для всех платформ. Строка компилируется в двоичный файл как статический строковый литерал. Если вы работаете с окнами, вы даже можете открыть свой .exe с помощью блокнота и выполнить поиск самой строки.

Поскольку это статическая строковая буква, не имеет значения.

Объединение строк:

Одна вещь, которую нужно обратить внимание, заключается в том, что в некоторых случаях идентичные строковые литералы могут быть "объединены", чтобы сэкономить место в исполняемом файле. В этом случае каждый строковый литерал, который был таким же, мог иметь одинаковый адрес памяти. Вы никогда не должны предполагать, что это будет или не будет иметь место.

В большинстве компиляторов вы можете установить, следует ли использовать статический пул строк для литералов-стимуляторов.

Максимальный размер строковых литералов:

Несколько компиляторов имеют максимальный размер для строкового литерала. Например, с VС++ это примерно 2048 байт.

Изменение строкового литерала дает поведение undefined:

Изменение строкового литерала никогда не должно выполняться. Он имеет поведение undefined.

char * sz = "this is a test";
sz[0] = 'T'; //<--- undefined results

Широкие строковые литералы:

Все вышеизложенное применимо в равной степени к широким строковым литералам.

Пример: L "это широкий строковый литерал";

Стандарт С++: (раздел lex.string)

1 Строковый литерал представляет собой последовательность символов (как определено в lex.ccon), окруженный двойными кавычками, необязательно, начиная с буква L, как в "..." или "L "...". Строковый литерал, который не начинается с L - обычный строковый литерал, также называемый узким строковый литерал. Обычный строковый литерал имеет тип "массив из n Const char "и статической продолжительности хранения (basic.stc), где n - размер строки, как определено ниже, и инициализируется данным персонажи. Строковый литерал, начинающийся с L, такой как L" asdf ", является широкий строковый литерал. Широкий строковый литерал имеет тип" массив N const wchar_t "и имеет статическую продолжительность хранения, где n - размер из строка, как определено ниже, и инициализируется с заданным символом Ослабляет.

2 Независимы ли все строковые литералы (то есть, хранятся в   неперекрывающиеся объекты) определяется реализацией. Эффект из  попытка изменить строковый литерал undefined.

Ответ 2

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

char *f()
{
char a[]="SUMIT";
return a;
}

это не работает.

но

char *f()
{
char *a="SUMIT";
return a;
}

это работает.

Причина: "СУММА" - это литерал, имеющий глобальную область действия. в то время как массив, который является просто последовательностью символов {'S', 'U', 'M', 'I', "T ''\0 '} имеет ограниченный объем, и он исчезает, как только возвращается программа.

Надеюсь, что это поможет

Ответ 3

Да, это хорошо. Они живут в глобальной таблице строк.

Ответ 4

Нет, строковые литералы не имеют области видимости, поэтому ваш код гарантированно работает во всех платформах и компиляторах. Они хранятся в двоичном образе программы, поэтому вы всегда можете получить к ним доступ. Однако попытка написать им (отбрасывая const) приведет к поведению undefined.

Ответ 5

Это справедливо в C (или С++), как объяснили другие.

Единственное, что я могу думать, чтобы следить за тем, что, если вы используете DLL, то указатель не останется действительным, если dll, содержащий этот код, будет выгружен.

Стандарт C (или С++) не понимает или не учитывает загрузку и выгрузку кода во время выполнения, поэтому все, что делает это, будет иметь последствия, связанные с реализацией: в этом случае следствием является то, что строковый литерал, который является который должен иметь статическую продолжительность хранения, появляется из POV вызывающего кода, чтобы он не сохранялся в течение всей продолжительности программы.

Ответ 6

Фактически вы возвращаете указатель на строку с нулевым завершением, хранящуюся в разделе данных исполняемого файла, область, загружаемую при загрузке программы. Просто не пытайтесь изменить персонажей, это может дать непредсказуемые результаты...

Ответ 7

Очень важно отметить результаты undefined, о которых говорил Брайан. Поскольку вы объявили функцию как возвращающую тип const char *, вы должны быть в порядке, но на многих платформах строковые литералы помещаются в сегмент только для чтения в исполняемом файле (обычно в текстовом сегменте) и изменяя их, нарушение доступа на большинстве платформ.