Указатель и адрес к этому указателю приводят к тому же

Когда я увидел эти строки:

BYTE MessageToProcess[MAX_MESSAGE_LENGTH];
TcpIpPacketHdr *pHdr = (TcpIpPacketHdr*)&MessageToProcess;

Я сказал себе, что вторая строка должна быть такой:

TcpIpPacketHdr *pHdr = (TcpIpPacketHdr*)MessageToProcess;

Но когда я проверил в режиме отладки, "pHdr" указывает на то же, что и "MessageToProcess" в обоих примерах, тогда как "&" перед MessageToProcess в первом коде, поэтому обычно pHdr должен содержать адрес MessageToProcess, а не адрес байта, который указывает, например, на первый элемент в messageToProcess.

Итак, вопрос Что происходит? мы имеем дело с указателями на байты, а не с функциями, поэтому добавляем и должны изменять уравнение.

Позже в коде мы используем pHdr следующим образом:

pHdr->size+2

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

Ответы

Ответ 1

Переменная MessageToProcess - это массив. Он размещен где-то в памяти. Используя &MessageToProcess, мы получаем адрес этого места в памяти, где хранится массив. Тип &MessageToProcess - BYTE (*)[MAX_MESSAGE_LENGTH].

Когда вы используете MessageToProcess без оператора адреса, он распадается на указатель на первый элемент, т.е. &MessageToProcess[0]. Типом этого является BYTE *.

Для чего-то простого, как примеры, показанные в вопросе, эти два адреса одинаковы. Разница возникает, когда вы пытаетесь сделать что-то еще с этими указателями. Например, если вы делаете (&MessageToProcess)[1], вы не получите то же самое, что при выполнении MessageToProcess[1].


Чтобы визуализировать это несколько, скажем, мы имеем следующее определение:

int a[4] = { 0, 1, 2, 3 };

Затем это примерно так:

&a              &a+1
|               |
v               v
+---+---+---+---+
| 0 | 1 | 2 | 3 |
+---+---+---+---+
^   ^
|   |
a   a+1

Ответ 2

MessageToProcess - это массив.

В случае массива базовый адрес массива может быть указан следующими способами:

&MessageToProcess ИЛИ MessageToProcess ИЛИ &MessageToProcess[0].