Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Если ссылаться на постоянные строки символов с помощью указателей, постоянно ли занята память?

Автор вопроса: spectraОтветов: 3

Я пытаюсь понять, где вещи хранятся в памяти (стек/куча, есть ли другие?) при запуске программы c. При компиляции выдается предупреждение: функция возвращает адрес локальной переменной:

char *giveString (void)
{
    char string[] = "Test";
    return string;
}
int main (void)
{
    char *string = giveString ();
    printf ("%s\n", string);
}

Запуск дает разные результаты, просто печатает тарабарщину. Из этого я понял, что массив символов, называемый строкой в ​​функции giveString(), сохраняется в кадре стека функции giveString() во время ее работы. Но если я изменю тип строки в giveString() с массива char на указатель char:

char *string = "Test";

Я не получаю предупреждений, и программа выводит "Тест". Значит ли это, что строка символов "Test" теперь находится в куче? Он определенно больше не находится в кадре стека giveString(). Что именно происходит в каждом из этих двух случаев? И если эта строка символов расположена в куче, так что все части программы могут получить к ней доступ через указатель, будет ли она никогда не освобождена до завершения программы? Или освободилось бы место в памяти, если бы на него не было указателей, например, если бы я не вернул указатель на main? (Но это возможно только со сборщиком мусора, как в Java, верно?) Является ли это особым случаем выделения кучи, который применим только к указателям на постоянные строки символов (жестко запрограммированные строки)?

cpointersmalloc

Ответы

Ответ 1 · рейтинг 7 · Variable Length Coder

Вы, кажется, смущены тем, что делают следующие утверждения.

char string[] = "Test";

Этот код означает: создать в локальном кадре стека массив достаточного размера и скопировать в него содержимое константной строки "Test".

char *string = "Test";

Этот код означает: установите указатель так, чтобы он указывал на константную строку "Тест".

В обоих случаях "Тест" находится в сегменте const или cstring вашего двоичного файла, где существуют неизменяемые данные. Его нет ни в куче, ни в стеке. В первом случае вы создаете копию "Test", которую можете изменить, но эта копия исчезает после возврата вашей функции. В последнем случае вы просто указываете на него, поэтому вы можете использовать его, как только ваша функция вернется, но вы никогда не сможете его изменить.

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

Ответ 2 · Chris Eberle

Нет. Строка "Test" все еще находится в стеке, она находится только в части data стека, которая в основном настраивается до запуска программы. Он есть, но вы можете думать об этом как о "глобальных" данных.

Следующее может немного прояснить ситуацию для вас:

char string[] = "Test"; // declare a local array, and copy "Test" into it
char* string = "Test";  // declare a local pointer and point it at the "Test"
                        // string in the data section of the stack

Ответ 3 · Heisenbug

Это потому, что во втором случае вы создаете постоянную строку:

char *string = "Test";

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы