Совпадает ли адрес ссылки на разыменованный указатель с адресом указателя?

#c #pointers #reference #memory-address

#c #указатели #ссылка #адрес памяти

Вопрос:

В C гарантированно ли совпадает адрес ссылки на разыменованный указатель с адресом указателя?

Или, написанное в коде, гарантировано ли, что следующее утверждение всегда будет верным?

 SomeType *ptr = someAddress;
SomeType amp;ref = *ptr;
assert(amp;ref == ptr);
  

Комментарии:

1. @dlev: как он вообще мог «попробовать», гарантированно ли это будет то же самое? И зачем ему спрашивать, гарантировано ли это, если все, что он хочет знать, это является ли это равным для одного конкретного запуска одной конкретной программы в одной конкретной реализации C ?

2. @Steve он, очевидно, не может, но прогнать его пару раз должно быть более чем достаточно, чтобы убедить вас, что это правда. Тем не менее, вы правы, он действительно сказал » гарантировано «.

3. Код правильный, вопрос более «сомнительный». Я бы прочитал «адрес указателя» как amp;ptr , что не совпадает с адресом объекта, на который указывается.

4. @dlev: исходя из этого, я убежден, что sizeof(int) == sizeof(void*) это гарантировано. Я предсказываю, что впереди будут неприятности ;-). Мы знаем только то, что попытка использовать Jesper’s assert дает правильный ответ, потому что мы случайно знаем, что есть фундаментальная причина, по которой вы получите один и тот же ответ везде. Но если вы не знали, что он везде одинаков, то вы не могли полагаться на тест. И если бы вы знали, что везде одно и то же, вы бы уже знали ответ на вопрос…

5. @Steve что может пойти не так? В любом случае, это всего лишь байты.

Ответ №1:

Да, это правильно и всегда будет правдой.

Ссылка — это не что иное, как псевдоним типа, на который она ссылается. У него нет отдельного существования, оно всегда связано с тем, к кому оно относится.

Ответ №2:

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

Если вы хотите быть точным, то amp;ref на самом деле это не «адрес ссылки», а «адрес ссылочного элемента ссылки». Поскольку ref был привязан к *ptr , это означает, что referand of ref и referand (или pointee, если вы предпочитаете) of ptr являются одним и тем же объектом, и, следовательно, два адреса amp;ref и ptr равны.

И, как указывает Bo, то, с чем вы сравниваете amp;ref , является «значением указателя» или «адресом, хранящимся в указателе», а не «адресом указателя».

Комментарии:

1. 1 важно заметить, что amp;ref возвращает не адрес, где хранится сама ссылка, а адрес объекта, на который делается ссылка.

Ответ №3:

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

Ответ №4:

Да, ваше понимание верно. И для 99,9% кода в мире ваш код будет правильным. Для педантов в аудитории (и я среди них) это утверждение не всегда верно:

 SomeType *ptr = someAddress;
SomeType amp;ref = *ptr;
assert(amp;ref == ptr);
  

Рассмотрим эту программу:

 #include <cassert>
struct SomeType { void* operatoramp;() { return 0; } };
int main() {
  SomeType *ptr = new SomeType;
  SomeType amp;ref = *ptr;
  assert(amp;ref == ptr);
}
  

Комментарии:

1. Будучи педантичным, я не мог не заметить, что 99.(9) просто равно 100.