Как может быть так много регистровых переменных с таким ограниченным количеством регистров? - PullRequest
0 голосов
/ 09 октября 2018

Я дурачился с C и понял, по праву, если я объявлю кучу регистровых переменных, не будут ли значения перезаписаны?Из того, что я могу сказать из сборки, в микропроцессоре нет тонны регистров, недостаточно для удовлетворения созданного мною требования.Как С сохраняет все значения?

Ответы [ 5 ]

0 голосов
/ 09 октября 2018

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

int test(void)
{
  int x=0,y=0;
  int *p = &y;

  while(x < 10)
  {
    x++;
    foo();
    x++;
    *p *= 3;
    x++;
    bar();
    ...

, не сможет узнать, можно ли безопасно хранить значение x в регистре при вызове foo и / илиоперация на *p или может ли foo изменить значение x.

Цель ключевого слова register заключалась в том, чтобы эффективно сообщить компилятору, что это будет safe сохраняет значение объекта в регистре между вызовами функций или операциями, которые записывают в указатели, даже если он не видел всего, что код может делать с объектом.Такое значение может быть полезным даже сегодня, если передача адреса объекта во вложенную функцию не является нарушением ограничения, но компилятору было разрешено предполагать, что в любом контексте, где используется именованный объект lvalue, все операции будут включать в себя этот именованный-объектЕсли адрес объекта никогда не берется, квалификатор не потребовался бы для приглашения такого предположения, но в случаях, когда адрес объекта взят , но не сохранен в конфликтных операциях, связанных с объектом, такой классификатор может датьинформация о компиляторе, которую он не имел бы.

0 голосов
/ 09 октября 2018

register является подсказкой, что компилятор может хранить переменную в регистрах.Вы не можете заставить компилятор использовать больше регистров, чем существует в целевой архитектуре, по очевидной причине, что это невозможно.


В C ключевое слово register просто означает, что адрес переменной можетне будет принятоЭто мешает вам делать все, что мешает компилятору хранить его в регистре, но не требует, чтобы было в регистре.

С https://en.cppreference.com/w/c/language/storage_duration

Спецификатор регистра разрешен только для объектов, объявленных в области блока, включая списки параметров функции.Он указывает продолжительность автоматического хранения и отсутствие привязки (которая используется по умолчанию для объявлений такого типа), но дополнительно намекает оптимизатору сохранить значение этой переменной в регистре ЦП, если это возможно.Независимо от того, происходит эта оптимизация или нет, объявленный регистр переменных не может использоваться в качестве аргументов оператора address-of, он не может использовать alignas (начиная с C11), а массивы регистров не конвертируются в указатели.

В течение многих лет он ничего не делал: оптимизирующие компиляторы уже по возможности сохраняют переменные в regs.Для переменных, которые являются глобальными или у которых был взят их адрес, то, возможно, только для части функции, сохраняя результат обратно в память, если переменная не может быть оптимизирована.


BTW, register официально объявлен устаревшим в C ++, а C ++ 17 фактически удалил его из языка.https://en.cppreference.com/w/cpp/language/storage_duration.


Связанный: GNU C имеет register int foo asm("eax"); (или любой другой регистр), но даже это только гарантированно , чтобы иметь эффект при использовании в качестве операнда дляоператор inline-asm при использовании для локальных переменных.В текущих версиях GCC это заставляет компилятор использовать этот регистр для переменной, если только ему не нужно разлить / перезагрузить его, чтобы стек памяти при вызовах функций или что-то в этом роде.

https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html

Но в GNU C вы можете использовать глобальные переменные регистров, где регистр выделен глобальному на всю жизнь вашей программы, что мешает оптимизации кода, который не использует эту переменную.Это интересный вариант, но не тот, который вам следует использовать.

0 голосов
/ 09 октября 2018

Старый компилятор выделяет столько регистров для register переменных, сколько может (в некоторых случаях это число равно 0) и выделяет оставшиеся переменные в стеке.

Современные компиляторы обычно игнорируют register ключевое слово.Они используют сложные распределители регистров , которые автоматически сохраняют в регистрах столько переменных, сколько возможно.

Единственный эффект register, на который вы можете положиться, - это получение диагностического сообщения, если вы пытаетесьвзять адрес переменной регистра.В противном случае переменные регистра ведут себя так же, как автоматические переменные.

0 голосов
/ 09 октября 2018

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

0 голосов
/ 09 октября 2018

Не требуется, чтобы все переменные, объявленные с register, были сохранены в регистрах ЦП.

Вот что говорит стандарт C:

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

Ссылка: ISO C11 N1570 черновик , пункт 6.7.1, пункт 6. Обратите внимание, что в нем даже не упоминается процессоррегистры.

Соответствующий компилятор может просто игнорировать все ключевые слова register (не считая наложения некоторых ограничений на получение адреса register объектов).

На практике большинство компиляторов просто помещаютстолько register переменных в регистрах ЦП, сколько они могут.

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

В наши дни принято считать, что ключевое слово register не дает больших преимуществ.

...