Как имена/адреса памяти переменных представлены на битовом уровне?

Это может быть глупый вопрос, но я довольно новичок в программировании, так что терпите меня.

Допустим, ради аргумента я говорю о кодировании на C...

Я понимаю, что (зависит от системы) int занимает 4 байта или 32 бита памяти.

Однако здесь есть две вещи, которые меня смущают. С этим фрагментом памяти связан определенный адрес памяти (который, скажем, также 32-битный), и если сохранить это целое число в переменной, то с ним также будет связано имя.

например интервал myInt = 5;

Мой вопрос - как и где адрес памяти и имя переменной представлены на битовом уровне? При компиляции кода компилятор в основном говорит: «Хорошо, myInt ссылается на адрес 0xffffff» и по существу заменяет адрес памяти в машинном коде? Даже если бы это было так, я все еще не понимаю, как представлен сам адрес памяти...

Я надеюсь, что мое замешательство достаточно ясно!


person Daniel Graef    schedule 31.01.2012    source источник


Ответы (2)


Теоретически ответ это зависит от реализации. Каждый компилятор C выбирает наилучший подход - пока он демонстрирует правильное поведение, на самом деле не имеет значения, как вы туда попали.

С практической точки зрения вы, вероятно, не увидите ссылки на имена переменных в скомпилированной программе. Это потому, что процессору не нужно знать или заботиться об именах переменных, которые вы присвоили для выполнения вашей программы. Он работает на гораздо более низком уровне: ему просто нужно понять, какие инструкции выполнять и в каком порядке. Поэтому включение этой информации является излишним расточительством, которое просто раздует размер вашей программы.

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

  • Для локальных переменных, как часть процесса компиляции, компилятор заменяет каждое имя переменной (например, «int foo;») ссылкой на соответствующую память, выделенную для этой переменной («адрес памяти 0x482c»). Присвоения или ссылки на это значение обычно могут просто ссылаться на соответствующий адрес.

  • Для нелокальных переменных компилятор выполняет дополнительное разрешение, чтобы определить, как обнаружить, но обычно он по-прежнему не сохраняет имя переменной или функции напрямую.

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

В некоторых случаях полезно включать имена переменных в вывод компилятора, например, при отладке. В таких случаях создается таблица символов отладки. Это способ сопоставить адреса с именами, которые имеют смысл для людей, чтобы при сбое вы могли видеть "Stacktrace: function foo() ..." вместо этого. из "Stacktrace: адрес памяти 0x4572...".

В языках с возможностями метапрограммирования, таких как C#, Ruby или Java, имена часто становятся частью метаданных, которые хранятся вместе с объектом, а не просто заменяют каждую ссылку поиском по адресу памяти. Эти метаданные пригодятся, когда вы хотите проделать некоторые изящные трюки, которые почти невозможны в C во время выполнения, например спросить: «У каких объектов в этой коллекции есть поле с именем foo?».

person John Feminella    schedule 31.01.2012
comment
Действительно интересные вещи. Спасибо! - person Daniel Graef; 31.01.2012

При компиляции кода компилятор в основном говорит: "ОК, myInt ссылается на адрес 0xffffff" и фактически подставляет адрес памяти в машинном коде?

Если myInt находится в стеке, смещение от указателя стека откладывается. Компилятор запомнит наличие myInt во время компиляции этой функции.

Если myInt имеет глобальную или файловую область, она остается myInt до тех пор, пока компоновщик не выберет абсолютное местоположение.

Я все еще не понимаю, как представлен сам адрес памяти...

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

person Drew Dormann    schedule 31.01.2012
comment
Хорошо, так что (вероятно, немного эзотерический вопрос), как каждый бит памяти знает свой адрес? Я понимаю, что нумеруются они последовательно, но где хранится эта нумерация байт? Итак, если конкретный байт в памяти имеет адрес 0xFFFFFF, для хранения самого этого адреса, как это делает указатель, потребуется 32 бита, поэтому это похоже на бесконечный цикл - каждому байту нужен адрес размером в байт, чтобы знать, где он находится. - person Daniel Graef; 31.01.2012
comment
@DanielGraef: биты (обычно не адресуемые, поэтому обычно не имеют адресов) и байты не знают своих собственных адресов. Нумерация подразумевается логикой декодирования адреса микросхемы памяти и тем, как адресные линии подключаются к адресной шине ЦП и, возможно, снова модифицируются такими вещами, как MMU. - person tinman; 31.01.2012
comment
@DanielGraef: Это не так. Каждый бит понятия не имеет, где он находится, так сказать. Поскольку эти байты пронумерованы по порядку, когда процессору нужны данные по определенному адресу, он может математически вычислить, где эти данные. Ему не нужно читать адрес откуда угодно. - person Drew Dormann; 31.01.2012
comment
А, хорошо, спасибо большое, ребята. Надеюсь, вы оцените, что это немного сбивает с толку новичка! - person Daniel Graef; 31.01.2012
comment
@DanielGraef: Поскольку вы новичок, представьте, что я попросил у вас седьмую книгу на полке. 7-я книга нигде не будет написана. И 7-я книга не будет знать, что это 7-я книга. Но вы бы косвенно (математически?) знали, какую книгу мне передать. - person Drew Dormann; 31.01.2012
comment
Да, я понимаю, что процессор теперь может определить адрес памяти. Я запутался, думая, что адрес физически хранится где-то в памяти... Спасибо, что прояснили! - person Daniel Graef; 01.02.2012