Я читал, что gcc поддерживает определение глобальных переменных как переменных, хранящихся в регистре. Я хочу знать, есть ли в стандартах какие-либо спецификации для этой поддержки.
Определяют ли стандарты языка C поддержку переменных глобального регистра?
Ответы (5)
Существует распространенное заблуждение, что ключевое слово register
языка C говорит об аппаратных регистрах. Это может быть источником этой концепции, но в современном C это не цель. Единственный реальный эффект, который имеет register
, заключается в том, что &
не допускается на таком звере.
Они могут быть реализованы любым способом, который захочет компилятор, аппаратными регистрами, непосредственными инструкциями или в стеке, вы бы не знали. Что вы знаете, так это то, что переменная register
не может быть псевдонимом с другими переменными.
И, чтобы ответить на ваш вопрос более прямо, register
в области файлов не является частью языка C. Если бы это было так, это позволило бы нам объявить register const
переменных практически любой базы, которые могли бы служить своего рода глобальные константы.
Сопоставление аппаратного регистра с конкретными переменными — это расширение, предоставляемое компиляторами, например, gcc. Функция Gcc, как расширение, также работает в области файлов. Но это довольно непомерно, поскольку обычно у ЦП не так много аппаратных регистров.
register
нельзя использовать для глобальных переменных. Это предусмотрено C11 6.9/2:
Ограничения
Спецификаторы класса хранения
auto
иregister
не должны появляться в спецификаторах объявления во внешнем объявлении.
Здесь внешнее объявление означает любое объявление, которое не находится внутри функции. (Не путать с extern
или внешней связью).
Прежде всего. выделение регистровых хранимых переменных, если таковые имеются, является работой компилятора. C
стандарт не указывает ничего обязательного по этому поводу.
Тем не менее,
- #P3# <блочная цитата> #P4# блочная цитата>
- #P5# <блочная цитата> #P6# блочная цитата>
extern int foo; extern int *bar;
, код foo++; *bar ^= 1; foo++; *bar ^= 2;
должен выполнить все четыре шага по порядку. Если бы foo
можно было уточнить по регистру, операции можно было бы переупорядочить как foo+=2; *bar^=3;
.
- person supercat; 28.01.2016
Переменные глобального регистра не поддерживаются или не разрешены C99 или C11. стандарты (см. Sourav Ghosh или ответы Мэтта Макнабба).
В качестве расширения GCC принимает
register int *foo asm ("a5");
объявить глобальную переменную int
, находящуюся в регистре a5
... Это очень редко бывает полезно, и вам нужно понимать, как GCC генерирует код и выделяет регистры, каковы соглашения о вызовах вашего ABI, .. ... чтобы иметь возможность использовать это без опасений... Кстати, это, вероятно, ослабляет возможности оптимизации GCC.
Но если это специфично для GCC, Clang/LLVM делает не поддерживает это расширение, даже если оно поддерживает несколько других расширений GCC (например, вычисленные goto
-s, ...).
Нет. В стандартах не указана такая функция. Класс хранения register
ведет себя как auto
и не может использоваться для глобальных переменных.
Как правило, все, что свойственно определенной машине, не является частью стандарта C.