Глядя на С11 6.3.2.1 пункта 3:Почему индексирование массива регистра не определено?
исключением случаев, когда это операнд оператора
sizeof
, оператор_Alignof
или унарный оператор&
, или строковый литерал используется для инициализации массива, выражение, которое имеет тип «массив типа», преобразуется в выражение с типом «указатель на тип», который указывает на начальный элемент объекта массива и не является значением lvalue. Если объект массива имеет класс храненияregister
, поведение не определено.
Неопределенное поведение кажется странным выбором для этой ситуации. Неопределенное поведение «не предъявляет требований» (3.4.3). Другими словами, согласно только формулировке 6.3.2.1, индексирование (или выполнение нескольких других операций с) массива, объявленного с помощью register
, предположительно разрешено компилировать, запускать и выполнять именно то, что код выглядит так, как без него ошибка.
register int a[5];
a[0] = 6; // apparently not required to cause an error?
Это, кажется, противоречит духу ключевому слову, которое (в 6.5.3.2) предотвращает адрес именующей в настоящее время принимается с &
. Это не совсем то же самое, но это, безусловно, связано, как неявное преобразование указателя на массив-> и &
на lvalue, генерирует такой же результат: указатель на хранилище объекта.
В сноске к 6.7.1 делает эту связь явной:
адрес любой части объекта заявленного с хранения класса спецификатора
register
не может быть вычислено, либо в явном виде (с использованием одноместной&
оператора как обсуждалось в 6.5.3.2) или неявно (путем преобразования имени массива в указатель, как описано в 6.3.2.1).
Так что, если он «не может» быть сделано, почему это преобразование ип определяется вместо ошибочны, или (для индексации, где есть несколько других вариантов) от реализации?
Он не читается как надзор в 6.3.2.1, поскольку значение register
достаточно прост в соответствии с другими упоминаниями; Я бы предположил, что это было совершенно четко, если бы в этом предложении не говорилось иначе. В чем сомневаться?
Связано с [Возможно сохранение целого массива в регистре cpu] (http://stackoverflow.com/q/17342881/1708801), я недавно видел этот вопрос, хотя я не могу вспомнить, почему. –
Интересно, было ли намерение разрешать расширения, но не накладывать никаких требований на их точное значение?Существует много ситуаций, когда C страдает от того, что не имеет термина, значение которого менее жестко, чем определено в Реализации (которое требует, чтобы реализации указывали что-либо) или Unspecified (что требует выбора из фиксированного набора вариантов), но не так свободно, как Undefined (все идет). Лично я считаю, что 'register' может быть полезным ключевым словом, если функция, которая приняла параметр типа' register int * ', обещала не сохранять указатель и, следовательно, вызывающие функции такого типа ... – supercat
... может содержать переменные адрес которого был передан этой функции (но не был вообще открыт), мог сохранить эти переменные в кешках в регистрах при вызове других функций (которые могли бы, но для ключевого слова register *, иметь доступ к указателям, сохраненным более ранними вызовами функций). – supercat