Почему массивы символов теряются при возврате из функции в C ++? - PullRequest
1 голос
/ 09 ноября 2019

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

Печатается следующий код:

(null)
5
char* getString() 
{ 
  char arr[] = "SomeText";
  return arr;  
}      

int getInt()
{
    int b = 5;
    return b;
}

int main() 
{ 
  printf("%s", getString());
  printf("\n");
  printf("%d", getInt());

  return 0; 
} 

В стеке создаются переменные arr и b, поэтому они должны быть уничтожены после завершения функций. Мой вопрос: почему переменная b не теряется, а переменная arr теряется?

Ответы [ 2 ]

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

И getInt, и getString возвращают значение.

getInt возвращает значение int, равное 5. В вызывающей программе остается значение 5.

getString возвращаетchar * значение, которое указывает на arr. В то время как вызывающая сторона получает указатель, вещь, на которую он указывает, arr, больше не существует (в модели вычислений стандарта C), когда функция возвращает.

Таким образом, это не значение, возвращаемоефункция, которая является проблемой столько, сколько ее значение. Число 5 сохраняет свое значение. Указатель на вещь, которая перестает существовать, не сохраняет своего значения.

2 голосов
/ 09 ноября 2019

Уникальная и часто сбивающая с толку особенность C (и унаследованная C ++) заключается в том, что массив при использовании в выражении рассматривается не как набор значений, а (в большинстве случаев) как указатель на его первый элемент. Итак, когда вы возвращаете массив из функции, вы возвращаете адрес ее первого элемента.

Разыменование адреса объекта с автоматическим хранением продолжительностито, что больше не находится в области видимости, приводит к неопределенному поведению.

Когда вы возвращаете значение из функции, копия значения возвращается вызывающей стороне.

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

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


Есть 3 исключения: (1) в качестве операнда для &;(2) как операнд к sizeof;и (3) строковый литерал, используемый для инициализации массива. В C ++ есть и другие исключения: (4) в качестве операнда decltype;(5) в качестве аргумента функции для ссылочного параметра;(6) Объект для инициализации ссылочной переменной;... наверное, что-то еще, что я забыл ...

...