Где строковый литерал, переданный в вызов функции, хранится в c

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

//global
const char *s="Hello World \n";

Здесь строковый литерал "Hello World\n" получает хранилище в доступной только для чтения области программы. Теперь предположим, что я объявляю некоторый литерал в теле некоторой функции, такой как

func1(char *name)
{
    const char *s="Hello World\n";
}

Поскольку локальные переменные для функции хранятся в записи активации этой функции, то же самое относится и к строковым литералам? Снова предположим, что я вызываю func1 из некоторой функции func2 как

func2()
{
    //code
    char *s="Mary\n";

    //call1
    func1(s);

    //call2
    func1("Charles");

    //code
}

Здесь выше, при первом вызове func1 из func2, передается начальный адрес 's', т. Е. Адрес s[0], тогда как во втором вызове я не уверен, что на самом деле происходит. Где хранится строковый литерал "Charles". Создан ли компилятором какой-то темпериал и передан ли его адрес или что-то еще происходит? Я обнаружил, что литералы хранятся в разделе "только для чтения" из строковых литералов: куда они деваются? но мне неясно, происходит ли это только для глобальных литералов или для литералов, локальных для некоторой функции. Любое понимание будет заметно. Спасибо.

2 ответа

Решение

Строковый литерал A C представляет объект массива типа char[len+1], где len это длина плюс 1 для окончания '\0', Этот объект массива имеет статическую длительность хранения, что означает, что он существует для всего выполнения программы. Это применяется независимо от того, где появляется строковый литерал.

Сам литерал является типом выражения char[len+1], (В большинстве, но не во всех контекстах он будет неявно преобразован в char* значение, указывающее на первый символ.)

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

Если вы напишите это:

const char *s="Hello World\n";

внутри функции значение литерала такое, как я описал выше. Указатель объекта s инициализируется, чтобы указывать на первый символ объекта массива.

По историческим причинам строковые литералы не являются const в C, но попытка изменить соответствующий объект массива имеет неопределенное поведение. Объявление указателя const, как вы сделали здесь, не требуется, но это отличная идея.

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

Но на практике большинство компиляторов будут обрабатывать все строковые литералы одинаково, и, вероятно, все они окажутся в сегменте только для чтения. Таким образом, строковые литералы, используемые в качестве аргументов функции или используемые внутри функций, будут храниться в том же месте, что и "глобальные".

Другие вопросы по тегам