Указатели и объем памяти - PullRequest
7 голосов
/ 25 марта 2011

Я некоторое время программировал на C (но все еще довольно плохо знаком с C), и меня иногда смущает то, как C обрабатывает память.

Рассмотрим следующий допустимый фрагмент C:

const char *string(void)
{
       /* where is this pointer variable located in the memory? */
       const char *s;

       /* where is this text data located in the memory? */
       /* and when the program allocates memory for it?  */
       s = "Hello, World";

       return s;
}

int main(void)
{
    printf( "%s", string() );

    return 0;
}

Я спрашиваю, что именно происходит в памяти?Является ли переменная-указатель 's' локальной переменной или где переменная-указатель хранится в памяти.Кроме того, где текстовая константа «Hello, World» хранится в памяти (не считается ли это локальной переменной, которая недоступна после возврата функции)?

В основном, какие переменные / данные считаются в«локальная» область действия функций (перестает быть доступной после возврата функции)?

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

Ответы [ 5 ]

4 голосов
/ 25 марта 2011

Я спрашиваю, что именно происходит в памяти?

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

Разве переменная-указатель 's' не является локальной переменной?

Да

или где указатель переменной хранится в памяти?

Локальный s находится в регистре или в стеке.

Также, где текстовая константа "Hello, World" хранится в памяти?

В разделе .text или .data. Это константа, но старый код иногда изменяет их, поэтому это зависит от параметров компилятора. Вам нужно различать ссылку и объект, чтобы понять все это.

(не считается ли это локальной переменной, которая недоступна после возврата из функции)?

Хорошо, s локально, но сама строка будет требоваться каждый раз, когда вызывается функция, и локальный фрейм даже не будет существовать, пока это не произойдет, поэтому сама константа, скорее всего, хранится в разделе .text. , Он может храниться в .data, в зависимости от параметров компилятора и того, насколько текущая версия компилятора заботится о компиляции устаревшего кода. Литерал внутри выражения является чем-то совершенно отличным от переменной, которой он назначается.

В основном, какие переменные / данные считаются находящимися в «локальной» области функций (перестает быть доступным после возврата функции)?

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

2 голосов
/ 25 марта 2011

Компилятор уже подготовил хранилище строки "Hello, World" таким образом, что при загрузке вашего приложения он имеет собственный адрес памяти.

Затем, когда ваш код s = "Hello, World"; запускается, вы копируете адрес памяти скомпилированной строки в указатель s. Для этой строки не было выделено дополнительной памяти, и s сама является локальной переменной (указателем), временно занимающей место в стеке.

1 голос
/ 25 марта 2011

s находится в стеке и перестает существовать, когда возвращается string(). Литеральная строка хранится в данных программы, доступных только для чтения (это может или не может быть частью кода программы, в зависимости от компилятора и ОС); с gcc вы можете сделать его частью инициализированных данных для чтения и записи, скомпилировав с -fwritable-strings, но это плохая идея (в основном это предусмотрено для древних программ, которые ожидают, что строковые литералы будут доступны для записи).

1 голос
/ 25 марта 2011

s = "Hello, World"; s - локальная переменная, тогда как "Hello World", являющийся строковым литералом, хранится в постоянной области памяти и имеет статическую продолжительность хранения.s уничтожается, когда функция возвращается, а строковый литерал "Hello World" - нет.

0 голосов
/ 25 марта 2011

попробуйте это. май работает

#include 

static char* str1(void){
    static char* s="abc";
    return s;
}
int main(int argc,char* argv[]){
    printf("%s\n",str1());
    return 0;
}

'const' is 'не должно быть левозначным'. «static» для переменной, это «static static». (вы возвращаете статическую строку)

переменная s указывает на область, которая «статически распределена»

...