Это статически связано?

1

Скажем, что у меня есть программа на C, и она имеет следующую строку:

int a = 12;

Является ли значение 12 привязано к 'a' во время компиляции? Или значение, помещенное в память во время выполнения, когда область действия программы достигает "a"?

Как насчет языков программирования, таких как Python и Ruby?

Существуют ли языки/экземпляры, где значение статически привязано к переменной? Я уже давно об этом думаю, и я честно не могу думать о логической причине статической привязки значения к примитивному типу.

Теги:
binding
compiler-construction

4 ответа

2
Лучший ответ

Значение 12 не статически привязано к a. Скорее, a привязан к ячейке памяти, которая инициализируется значением 12.

Если a были объявлены как const, и ничто никогда не принимало его адрес, компилятору не нужно было бы выделять хранилище и использовать его как константу времени компиляции, и в этом случае значение 12 было бы статически связанный с a.

  • 0
    Может ли это быть постоянной времени компиляции (например, #define)? Что делать , если вы пытаетесь &a ?
  • 0
    @ Ник Т: Смотрите мое редактирование.
9

Компиляторы и виртуальные машины эффективно "реализуют" языки программирования. Они должны делать только то, что определено семантикой языка и наблюдаемое для данной программы, чтобы быть верным.

Когда вы пишете оператор определения int a = 12; в программе на C, вы сообщаете компилятору, что есть переменная с именем a, для которой начальное значение установлено на постоянный литерал двенадцать.

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

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

Если вы сделаете ссылку на a, a la int *aptr = &a;, тогда спецификация языка говорит, что a должно иметь место в памяти (IIRC). Это означает, что в соответствии с спецификацией в памяти будет установлен допустимый интервал размера в размере (в стеке, в любой разумной реализации), который будет содержать 12.

В других языках есть, очевидно, другие спецификации. Технически, в динамических языках компилятор может выполнять аналогичные оптимизации. Если у вас есть функция Python:

def do_nothing():
    a = 12

Можно предположить, что компилятор Python, который превращает текст языка в байт-коды, может полностью исключить тело этой функции (для педантов: кроме неявного return None). Традиционно реализации Python не имеют такой оптимизации, поскольку ее философия языка требует отладки, простоты реализации VM и понимания программистов выше оптимизаций.

Существуют также некоторые сложные конструкции в динамических языках, которые затрудняют вывод. Например, Python позволяет проводить большую проверку объектов кода, которая, как ожидается, будет работать во всех реализациях. Приобретение/проверка трассировки стека и локальные аргументы активированных кадров требуют, по крайней мере, механизмов замедления медленного пути, что значительно увеличивает сложность оптимизации. Мы отказываемся от поддержки некоторых из этих типов событий проверки на уровне языка-времени выполнения в JavaScript с версией ECMAScript 5.

Поддержка отладчиков сложна, отпустите оптимизацию!

  • 1
    +1 за подробности и интересную информацию о других языках.
1

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

В CPython он может делать подобные оптимизации в некоторых случаях, если он может обладать переменной (если только ее глобальная, то она будет загружена в кучу). В обычном Ruby он может делать что-то подобное. В Jython и JRuby они определенно оптимизируют то же самое, что и процесс JIT.

Я не полный эксперт, так как я только написал очень простые компиляторы, которые выводят на байт-код, чтобы быть JITed позже, и это было много лет назад.

0

Я думаю, что a не может быть статически привязана, потому что a не является константой, а это значит, что одновременно может быть более одного значения a (например, объявление a в рекурсивной функции), Важно, чтобы каждое значение a должно иметь отдельный адрес в памяти, что подразумевает, что a не может быть статически привязано к определенному одному адресу памяти.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню