-1

When I saw this those lines :

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

I said to myself the second line must be like this :

TcpIpPacketHdr *pHdr = (TcpIpPacketHdr*)MessageToProcess;

But when I checked in debug mode "pHdr" points to the same thing as "MessageToProcess" in both example, whereas, there is a "&" before MessageToProcess in the first code, so normally pHdr should contain the address of the MessageToProcess and not the address of the byte it is pointing to, for instance, the first element in the messageToProcess.

So the question What's happening ? we are dealing with pointers to bytes and not functions so adding & must change the equation.

Later in the code we are using pHdr like this :

pHdr->size+2

But initially, in the first code, it does contain the address of the pointer holding the address to the first byte of the array.

Aminos
  • 754
  • 1
  • 20
  • 40
  • Arrays decay to pointers. You'll find an explanation in any book on the language. – Cody Gray - on strike Mar 03 '16 at 11:48
  • and what about for example char**, a pointer to a pointer type is different from a pointer type – Aminos Mar 03 '16 at 11:50
  • This code probably has undefined behavior, check out the [strict aliasing rule](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). – Lundin Mar 03 '16 at 11:58
  • @Lundin CPPCheck didn't found any problems in the file where the line in question is located. – Aminos Mar 03 '16 at 12:19
  • @Aminos It depends a on the context, namely of how `TcpIpPacketHdr` is defined. If it is defined as a `char`, `BYTE` or `uint8_t` you shouldn't need to worry. If it is defined as a struct/union, you have several severe bugs in that single line, or at very least reliance on non-standard behavior. – Lundin Mar 03 '16 at 12:43
  • @CodyGray: Not always! `&` is one of the three exceptions. And even iff, they are converted to a different type. – too honest for this site Mar 03 '16 at 12:50
  • Yes, @Olaf. That is the secret to understanding the code. I had originally left that comment along with closing as a duplicate of a question that contained that follow-up explanation, but someone reopened it, presumably thinking that this was actually undefined behavior. Last I heard from them, they were looking it up in the spec to be sure. – Cody Gray - on strike Mar 03 '16 at 13:46
  • @CodyGray: Problem is the question is tagged C **and** C++. Both languages often behave differently, but I'm not sure they actually do (no time/interest to check the C++ standard). The prerequisite "... `pHdr` points to the same thing as ..." is wrong already. OP just obfuscates the actual situation by the (problematic) cast. – too honest for this site Mar 03 '16 at 13:48
  • 1
    Yes, that is a problem. It makes the question rather unanswerable. In particular, it is impossible to quote the behavior in question from a language specification. It also hard to demonstrate whether it is or is not undefined behavior. The fellow I mentioned probably had that issue. It is a good lesson in why questions shouldn't be tagged *both* C and C++ unless they really concern interoperability or intersection between the two languages. No reason to believe Aminos is compiling this code with both a C and C++ compiler. – Cody Gray - on strike Mar 03 '16 at 13:51

2 Answers2

8

The variable MessageToProcess is an array. It's placed somewhere in memory. By using &MessageToProcess we get the address of that place in memory where the array is stored. The type of &MessageToProcess is BYTE (*)[MAX_MESSAGE_LENGTH].

When you use MessageToProcess without the address-of operator, it decays to a pointer to the first element, i.e. &MessageToProcess[0]. The type of that is BYTE *.

For something simple as the examples shown in the question, those two addresses are the same. The difference comes when you try to do something more with these pointers. For example if you do (&MessageToProcess)[1] you will not get the same thing as when doing MessageToProcess[1].


To visualize it somewhat, lets say we have the following definition:

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

Then it's something like this:

&a              &a+1
|               |
v               v
+---+---+---+---+
| 0 | 1 | 2 | 3 |
+---+---+---+---+
^   ^
|   |
a   a+1
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • So, if MessageToProcess is a dynamically array BYTE * MessageToProcess = new BYTE[MAX_MESSAGE_LENGTH], the first code above should not be valid : TcpIpPacketHdr *pHdr = (TcpIpPacketHdr*)&MessageToProcess; is not anymore correct. Am I right ? – Aminos Mar 03 '16 at 11:55
  • 1
    @Aminos That's correct. If `MessageToProcess` is a pointer variable, then doing `&MessageToProcess` is a pointer to the pointer variable, i.e. a `BYTE **`. – Some programmer dude Mar 03 '16 at 11:57
  • Everything is clear now. It's amazing how I am still discovering things in C/C++. I understand why new languages like Java and Python are more preferred nowadays. – Aminos Mar 03 '16 at 12:02
3

MessageToProcess is an array.

In case of array, base address of array can be indicated by following ways alternatively:

&MessageToProcess OR MessageToProcess OR &MessageToProcess[0].

Vagish
  • 2,520
  • 19
  • 32
  • I thought &MessageToProcess[0] was different from &MessageToProcess, but as MessageToProcess is not a BYTE * so they are identical. There is in fact a difference between array and pointer – Aminos Mar 03 '16 at 12:22