Шрифт:
НАХОЖДЕНИЕ АДРЕСОВ: ОПЕРАЦИЯ &
В результате выполнения операции & определяется адрес ячейки памяти, которая соответствует переменной. Если pooh– имя переменной, то &pooh– ее адрес. Можно представить себе адрес как ячейку памяти, но можно рассматривать его и как метку, которая используется компьютером, для идентификации переменной. Предположим, мы имеем оператор
pooh = 24;
Пусть также адрес ячейки, где размещается переменная pooh– 12126. Тогда в результате выполнения оператора
printf(" %d %d\n" , pooh, &pooh);
получим
24 12126
Более того, машинный код, соответствующий первому оператору, словами можно выразить приблизительно так: "Поместить число 24 в ячейку с адресом 12126".
Воспользуемся указанной выше операцией для проверки того, в каких ячейках хранятся значения переменных, принадлежащих разным функциям, но имеющих одно и то же имя.
/* контроль адресов */
main
{
int pooh = 2, bah = 5;
printf(" Вmain, pooh = %d и&pooh = %u \n" , pooh, &pooh);
printf('B main, bah = %d и&bah = %u\n>/, bah, &bah);
mikado(pooh);
}
mikado(bah) int bah;
{
int pooh = 10;
printf("B mikado, pooh = %d и&pooh = %u\n, pooh, &pooh);
printf(" Вmikado, bah = %d и&bah = %u\n" , bah, &bah);
}
Мы воспользовались форматом %u (целое без знака) для вывода на печать адресов на тот случай, если их величины превысят максимально возможное значение числа типа int. В нашей вычислительной системе результат работы этой маленькой программы выглядит так:
Вmain, pooh = 2 и&pooh = 56002
B main, bah = 5 и&bah = 56004
B mikado, pooh = 10 и&pooh =55996
В mikado, bah = 2 и &bah = 56000.
О чем это говорит? Во-первых, две переменные pooh имеют различные адреса. То же самое верно и относительно переменных bah. Следовательно, как и было обещано, компьютер рассматривает их как четыре разные переменные. Во-вторых, при вызове mikado(pooh) величина (2) фактического аргумента (pooh из main) передастся формальному аргументу (bah из mikado). Обратите внимание, что было передано только значение переменной. Адреса двух переменных (pooh в main и bah в mikado) остаются различными.
Мы коснулись второго вопроса потому, что этот факт оказывается неверным для всех других языков. В той или иной процедуре Фортрана, например, можно использовать переменные вызывающей программы. Кроме того, в такой процедуре переменные могут иметь различные имена, но адреса их при этом будут совпадать. В языке Си подобные механизмы отсутствуют. Каждая функция использует свои собственные переменные. Это более предпочтительно, потому что "исходные" переменные не будут таинственным образом изменяться из-за того, что вызванная функция обладает побочным эффектом. Но это может также приводить и к некоторым трудностям, о чем и будет рассказано и следующем разделе.
ИЗМЕНЕНИЕ ПЕРЕМЕННЫХ В ВЫЗЫВАЮЩЕЙ ПРОГРАММЕ
Иногда требуется, чтобы одна функция могла изменять переменные, относящиеся к другой. Например, в задачах сортировки часто бывает необходимо осуществлять обмен значениями между двумя переменными. Предположим, у нас есть две переменные х и у и мы хотим, чтобы они обменялись своими значениями. Простая последовательность операторов
х = у;
y = х;
не является решением поставленной задачи, потому что к тому моменту, когда начнет выполняться оператор во второй строке, первоначальное значение переменной x будет потеряно. Чтобы сохранить это первоначальное значение, необходимо дополнить данный фрагмент еще одной строкой:
temp = х;
х = у;
у = temp;
Теперь у нас есть требуемый метод; реализуем его в виде некоторой функции, а также создадим драйвер для eе проверки. Чтобы сделать более ясным, какая переменная принадлежит функции main, а какая - функции interchange, мы будем использовать переменные х и у в первой из них, и u и v– во второй.