C - это язык программирования низкого уровня, и поведение, связанное с использованием памяти через переменные C, может немного сбивать с толку программистов, использующих языки с абстракциями более высокого уровня.
Давайте сначала разберем вашу функцию main
.
int p[32];
Когда в вашей программе вызывается функция, ей выделяется некоторый раздел в ОЗУ, назначенный вашему процессу.Этот раздел называется стеком.С помощью этого оператора вы сообщаете компилятору, что вашей функции (main
) нужно место для 32 целых чисел в стеке.Дальнейшие операторы, которые вы делаете с переменной p
, будут работать с этим пространством, зарезервированным для 32 целых чисел.
Обратите внимание, что вы ничего не говорите компилятору о том, как эта часть памяти назначена для p
инициализируется.Таким образом, все эти байты, выделенные для 32 целых чисел, будут хранить все, что они содержали до вызова вашей функции.
Давайте рассмотрим следующий.
int *q = p + 5;
Это очень похоже, но теперь вы спрашиваетедля некоторой памяти в стеке с размером, который может соответствовать «указателю на целое число».Указатель - это абстракция C для простого «адреса памяти с типом».Таким образом, это пространство будет использоваться для хранения адресов в памяти, и эти адреса будут ссылаться на другое пространство в ОЗУ, предназначенное для хранения целых чисел.
Вы также говорите компилятору инициализировать пространство стека для q
, со значением p + 5
.В отличие от пробела для 32 целых чисел (p
), пробел для q
будет инициализирован сразу после вызова вашей функции.
Выражение p + 5
применяет то, что называется "арифметикой указателей",Это используется для получения адреса в ОЗУ и увеличения или уменьшения в зависимости от необходимого смещения.Помните, p
был массивом, и массивы в C работают как указатели (адреса), когда они участвуют в арифметике указателей.Таким образом, на самом деле p + 5
означает «адрес, который является 5 целыми числами после того, как первый адрес p указывает на».В конечном итоге это «указатель на шестой элемент p
» (сначала это p[0]
), другими словами, адрес p[5]
.
f(q);
В этом утверждении выпередача адреса, хранящегося в q
, который оказался адресом шестого элемента в p
.Функция f
в свою очередь присваивает 35
местоположению в ОЗУ, указанному по этому адресу, следовательно, заменяя целое число, к которому будет обращаться p[5]
, на целочисленное значение 35
.
Прямо вВ этой точке p[5]
является единственным элементом в p
, который имеет инициализированное значение.Все другие целые числа в p
будут продолжать хранить то, что они держали до того, как main
был вызван во время инициализации вашей программы.
printf( "%d", p[5] );
Когда выполнение вернется обратно к main
, целое число, которое можетдоступ к p[5]
теперь установлен на 35
, и это именно то, что вы ожидаете увидеть с этим оператором printf
.