Как обычно разрешаются переменные с одинаковыми именами? - PullRequest
1 голос
/ 12 февраля 2012

Предположим, что это стек вызовов моей программы в конкретный момент:

|    b = 2       |
|    c = 3       | <- function f2
| return address |
| function args  |
|     ...        |
|    c = 10      | <- function f1
|     ...        |

f1() вызовов f2().

При ссылке на переменную cкак это разрешается? Выполняется ли линейный поиск в стеке сверху вниз, чтобы найти первую переменную с именем c в области видимости, или есть какой-то другой механизм, который позаботится об этом более эффективно?стек ищется каждый раз, разве это не будет издержками, когда ссылается на несуществующую переменную d, потому что в стеке будет производиться полный поиск, чтобы узнать, что в области действия нет такой переменной?

Ответы [ 3 ]

2 голосов
/ 12 февраля 2012

В C ++ во время выполнения переменные не имеют имен. Имена переменных есть только для удобства программиста. Переменные имеют область видимости в коде, они не имеют области видимости в стеке.

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

1 голос
/ 12 февраля 2012

Ссылки разрешаются областью, в зависимости от того, где переменная определена, а не от того, где она назначена.Поскольку в вашем примере вы не показываете ОПРЕДЕЛЕНИЯ, это невозможно сказать.

В языках на основе C нет вложенных процедур (игнорируя проблему "thunks" в некоторых из них), поэтому стек,По сути, не ищется.Однако в одной процедуре вы можете иметь статическую вложенность области с символами {}, и тогда самая внутренняя область (относительно точки отсчета) "выигрывает".В противном случае это область действия процедуры, область действия класса, а затем статическая / глобальная область.

1 голос
/ 12 февраля 2012

Компилятору (C или C ++) сложно организовать каждый фрейм вызова.

При преобразовании машинного кода, связанного с локальной переменной в вашем исходном коде, он переводит доступ и изменения локальных переменных в подходящие инструкции (часто с использованием указателя стека или фрейма в качестве некоторой базы).

Заданное местоположение в кадре вызова может (и обычно используется при оптимизации компилятора) использоваться для нескольких целей.

Некоторые локальные переменные не имеют контраргументов в кадре вызова: они существуют только в регистрах. Другие иногда разливаются. Хороший распределитель регистров изо всех сил пытается избежать разливов.

Расположение кадра вызова, распределение регистров, планирование инструкций - сложные задачи оптимизирующего компилятора.

Если вам интересно узнать немного о вашем наборе команд процессора x86, вы можете попробовать написать крошечный файл C ++ tiny.cc и скомпилировать его с помощью g++ -Wall -fverbose-asm -O -S tiny.cc, а затем посмотреть на сгенерированный tiny.s, например, с помощью. редактор типа gedit или emacs или пейджер типа less.

...