Предположим, что у меня есть функция, которая объявляет и инициализирует две локальные переменные, которые по умолчанию имеют продолжительность хранения auto
. Затем эта функция вызывает вторую функцию, которой она передает адреса этих двух локальных переменных. Может ли эта вторая функция безопасно использовать эти указатели?
Тривиальный программный пример, чтобы дополнить это описание:
#include <stdio.h>
int adder(int *a, int *b)
{
return *a + *b;
}
int main()
{
auto int a = 5; // `auto' is redundant; included for clarity
auto int b = 3;
// adder() gets the addresses of two auto variables! is this an issue?
int result = adder(&a, &b);
printf("5 + 3 = %d\n", result);
return 0;
}
Эта программа работает, как ожидалось, печать 5 + 3 = 8
.
Обычно, когда у меня возникают вопросы о C, я перехожу к стандарту, и это не было исключением. В частности, я проверил ISO/IEC 9899, §6.2.4. Там сказано, в частности:
4 Объект, идентификатор которого объявлен без связи и без спецификатор класса хранения
static
имеет автоматическую продолжительность хранения.5 Для такого объекта, который не имеет тип массива переменной длины, его время жизни продолжается от входа в блок, с которым он связанный до тех пор, пока выполнение этого блока не закончится каким-либо образом. (Ввод закрытый блок или вызов функции приостанавливает, но не заканчивается, выполнение текущего блока.) Если блок введен рекурсивно, каждый раз создается новый экземпляр объекта. Начальное значение объекта неопределенно. Если инициализация указана для объект, он выполняется каждый раз, когда декларация достигается в выполнение блока; в противном случае значение становится неопределенным каждый раз, когда декларация будет достигнута.
Читая это, я рассуждаю о следующих моментах:
-
Переменные
a
иb
имеют продолжительность храненияauto
, которую я сделал явным, используя ключевое словоauto
. -
Вызов функции
adder()
соответствует скобке в разделе 5 в частичной цитате выше. То есть, ввод функцииadder()
"приостанавливает, но не заканчивается", выполнение текущего блока (который являетсяmain()
). -
Так как блок
main()
не является "end [ed] каким-либо образом," хранение дляa
иb
гарантировано. Таким образом, доступ к ним с использованием адресов&a
и&b
, даже внутриadder()
, должен быть безопасным.
Итак, мой вопрос: я прав в этом? Или я просто получаю "повезло" и получаю доступ к ячейкам памяти, которые, по случайности, не были перезаписаны?
P.S. Я не смог найти точный ответ на этот вопрос через поиск Google или SO. Если вы можете, отметьте это как дубликат, и я удалю его.