Предположим, у нас есть:
char* a;
int i;
Многие вводные сведения о C++ (например, этот) предполагает, что rvalue a+i
и &a[i]
взаимозаменяемы. Я наивно верил в это несколько десятилетий, пока недавно не наткнулся на следующий текст (здесь), цитируемый с [dcl.ref]:
в частности, нулевая ссылка не может существовать в четко определенной программе, потому что единственный способ создать такую ссылку — это привязать ее к «объекту», полученному путем разыменования нулевого указателя, что приводит к неопределенному поведению.
Другими словами, «привязка» ссылочного объекта к нулевому разыменованию приводит к неопределенному поведению. Основываясь на контексте приведенного выше текста, можно сделать вывод, что простая оценка &a[i]
(в макросе offsetof
) считается "связывающей" ссылкой. Кроме того, существует мнение, что &a[i]
вызывает неопределенное поведение в случае, когда a=null
и i=0
. Это поведение отличается от a+i
(как минимум в C++ в случае a=null, i=0).
Это приводит как минимум к 2 вопросам о различиях между a+i
и &a[i]
:
Во-первых, какова базовая семантическая разница между a+i
и &a[i]
, которая вызывает эту разницу в поведении. Можно ли это объяснить с точки зрения каких-либо общих принципов, а не просто «привязка ссылки к объекту разыменования null вызывает неопределенное поведение только потому, что это очень специфический случай, который всем известен»? Может ли &a[i]
генерировать доступ к памяти для a[i]
? Или автора спецификации не устраивали нулевые разыменования в тот день? Или что-то другое?
Во-вторых, помимо случая, когда a=null
и i=0
, есть ли другие случаи, когда a+i
и &a[i]
ведут себя по-разному? (может быть охвачен первым вопросом, в зависимости от ответа на него.)
a+i
не определено, еслиa=null
, хотя ваша 4-я ссылка говорит об этом является определенным, еслиi=0
, хммм - person kmdreko   schedule 01.03.2019a=null
,i=0
, чтобы установить, что существует a разница междуa+i
и&a[i]
... Опять же, заставляя задуматься, есть ли какие-либо другие различия между ними. - person personal_cloud   schedule 01.03.2019&*a
, когдаa
является нулевым указателем. Это является предметом ошибки 232. - person n. 1.8e9-where's-my-share m.   schedule 01.03.2019a
равноnull
или одному после последнего элемента массива. Это почти два самых полезных случая пустого lvalue! Но почему они остановились на этом, а не сделалиa+i
и&a[i]
полностью эквивалентными...? - person personal_cloud   schedule 01.03.2019a+i
и&a[i]
, а скорее просто некоторые разногласия и/или неверные толкования спецификации, применяемые по-разному к тому или иному синтаксису, без особого намерения применять только к тому или иному синтаксису. Таким образом создается впечатление, что междуa+i
и&a[i]
есть разница, хотя на самом деле разницы нет? Если кто-то считает, что C++ имеет ограничения на арифметику указателей, то можно ли применить те же ограничения и кa+i
, и к&a[i]
? (но сами ограничения омрачены спорами). - person personal_cloud   schedule 01.03.2019a+i
, и к&a[i]
? - person personal_cloud   schedule 01.03.2019&a[i]
, но неa+i
. Однако, возможно, это не относится к C++, как указано в статье Доббса. - person personal_cloud   schedule 01.03.2019offsetof
оценивает&a[i]
. - person cpplearner   schedule 01.03.2019&a[i]
считается обязательным для ссылки? - person Language Lawyer   schedule 01.03.2019a[i]
иi[a]
на самом деле взаимозаменяемы… потому что C. (Попробуйте.) - person Arne Vogel   schedule 01.03.2019