Область переменных C

Возможный дубликат:
Возврат адреса строкового литерала из функции безопасен и переносим?
время жизни строкового литерала в C

Привет я немного запутался

char *func()
 {

    return "Hello";
 }

Здесь «Hello» — это последовательность/массив символов. Это локальная переменная, и она должна исчезнуть, как только функция вернется. Тогда как же мы можем получить правильное значение?


person Community    schedule 27.08.2012    source источник
comment
Это не УБ? Разве вы не получили предупреждение от своего компилятора?   -  person Neel Basu    schedule 27.08.2012
comment
Нет, в данном случае нет, так как строка хранится в постоянном адресе памяти.   -  person Constantinius    schedule 27.08.2012
comment
Но он возвращается char* не const char* разве это не УБ?   -  person Neel Basu    schedule 27.08.2012
comment
@NeelBasu Строковые литералы не размещены в стеке?   -  person    schedule 27.08.2012
comment
@Constantinius Строковые литералы не размещены в стеке?   -  person    schedule 27.08.2012


Ответы (4)


"Hello" — это строковый литерал, который будет существовать в течение всего времени существования программы. Чтобы процитировать соответствующие разделы стандарта C99:

  • 6.4.5 Строковые литералы

...Последовательность многобайтовых символов затем используется для инициализации массива длительности статического хранения и длины, достаточной для хранения последовательности...

  • 6.2.4 Сроки хранения объектов

Объект, идентификатор которого объявлен с внешней или внутренней связью или со спецификатором класса хранения static, имеет длительность статического хранения. Его время жизни равно всему выполнению программы, а его сохраненное значение инициализируется только один раз перед запуском программы.

Возвращаемое значение функции должно быть const char*, так как попытка изменить строковый литерал является неопределенным поведением.

person hmjd    schedule 27.08.2012
comment
Литералы Strin не хранятся в стеке? Они выделяются из кучи? - person ; 27.08.2012
comment
@GreatCoder Они выделены в постоянной памяти, вероятно, называемой .rodata или подобной компоновочной тарабарщиной. - person Lundin; 27.08.2012
comment
@GreatCoder, они не хранятся в стеке или куче. Они будут скомпилированы непосредственно в созданный двоичный файл. Я думаю, область двоичного файла, в которую компилируются строковые литералы, называется областью данных. - person hmjd; 27.08.2012
comment
@hmjd Обычно компоновщик будет иметь один сегмент .data и один сегмент .rodata, где первый предназначен для всех переменных длительности статического хранения (которые не инициализированы нулем, они находятся в .bss), а второй предназначен для переменных только для чтения, т.е. констант и строковые литералы. - person Lundin; 27.08.2012
comment
@Lundin, спасибо. Я знал о двух разделах (инициализированных и нет), но не знал их имен. - person hmjd; 27.08.2012
comment
Один из способов думать об этом — рассматривать строковый литерал, такой как "a", как эквивалентный объявлению static const char string_a[] = {'a', '\0'};, и что все случаи использования "a" должны быть заменены на string_a в глобальном масштабе, при этом коллизии, вероятно, также будут свернуты. - person unwind; 27.08.2012

Он постоянный и имеет постоянный адрес в памяти.

person nshy    schedule 27.08.2012
comment
как ? он никогда не указывал const - person Neel Basu; 27.08.2012
comment
@NeelBasu Хорошо, точнее, это строковый литерал. - person nshy; 27.08.2012
comment
это всегда имеет место для строкового литерала. - person Hicham; 27.08.2012

Функция уничтожает значения только после возврата элемента управления.

Итак, к тому времени, когда встречается оператор return, "Hello" помещается в возвращаемое значение, а затем функция уничтожает область действия;

person vivek_jonam    schedule 27.08.2012
comment
Тогда он должен рухнуть во время выполнения. вопрос упоминает Тогда как же мы можем получить правильное значение - person Neel Basu; 27.08.2012
comment
Вы ошибаетесь, поскольку строковый литерал не является локальной (автоматической) переменной и не размещается в стеке, а является постоянной статической памятью только для чтения. - person Lundin; 27.08.2012

взгляните на это: возвращается адрес строкового литерала из безопасной и переносимой функции?

даже если строка была удалена (локальная переменная или динамическое выделение с помощью malloc() и free()), когда вы возвращаете указатель, значение может быть правильным. но это неопределенное поведение.

person Hicham    schedule 27.08.2012