Основы памяти стека - PullRequest
       5

Основы памяти стека

3 голосов
/ 09 ноября 2009

Рассмотрим этот код:

 char* foo(int myNum) {
    char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

    return StrArray[4];
 }

Когда я возвращаю StrArray[4] вызывающей стороне, это должно работать? Поскольку массив определен в стеке, когда вызывающая сторона получает указатель, эта часть памяти вышла из области видимости. Или этот код будет работать?

Ответы [ 5 ]

8 голосов
/ 09 ноября 2009

Этот код будет работать. Вы возвращаете значение указателя в StrArray[4], которое указывает на постоянную строку "BB". Время жизни константных строк равно времени жизни всей вашей программы.

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

char* foo(int myNum) {
   char bb[3] = "BB";
   char* StrArray[5] = {"TEST","ABC","XYZ","AA",bb};

   return StrArray[4];
}

Это связано с тем, что массив bb является временным значением в стеке функции foo() и исчезает при возврате.

4 голосов
/ 09 ноября 2009

Осторожно: вы врете компилятору.

Каждый элемент StrArray указывает на только для чтения char *;
Вы говорите компилятору, что возвращаемое значение вашей функции - модифицируемое char *.
Обмани компилятору, и он рано или поздно отомстит.

В C способ объявления указателя на данные только для чтения состоит в том, чтобы квалифицировать его как const.

Я бы написал ваш код как:

const char* foo(int myNum) {
   const char* StrArray[5] = {"TEST","ABC","XYZ","AA","BB"};

   return StrArray[4];
}
2 голосов
/ 09 ноября 2009

Код будет работать. Точка, которую вы возвращаете (StrArray[4]), указывает на строковый литерал "BB". Строковые литералы в C - это анонимные объекты массива со статической продолжительностью хранения , что означает, что они живут столько, сколько ваша программа (т.е. Неважно, где вы создаете этот жало буквальный. Даже если он введен внутри функции, он все равно имеет статическую продолжительность хранения.

Просто помните, что строковые литералы не могут быть изменены, поэтому лучше использовать const char* указатели со строковыми литералами.

0 голосов
/ 10 ноября 2009

В стеке находится только массив указателей, а не строковые литеральные константы.

0 голосов
/ 09 ноября 2009

C использует массивы с указателями, начинающимися с 0. Таким образом, первый элемент - StrArray [0]

Таким образом, StrArray [5] не был объявлен в вашем коде.

C позволит вам написать код, возвращающий StrArray [5], но это не определено и будет отличаться в ОС и компиляторе, но часто приводит к сбою программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...