Pointer initialisation quirk

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I'm having a problem with a bit of code that initialises a pointer.

478:      	uint16_t lRealLength = 0;
+000006FB:   821C        STD     Y+4,R1           Store indirect with displacement
+000006FC:   821B        STD     Y+3,R1           Store indirect with displacement
479:      	uint16_t lTrackLength = 1;
+000006FD:   E081        LDI     R24,0x01         Load immediate
+000006FE:   E090        LDI     R25,0x00         Load immediate
+000006FF:   839E        STD     Y+6,R25          Store indirect with displacement
+00000700:   838D        STD     Y+5,R24          Store indirect with displacement
480:      	uint8_t* pData = (uint8_t *)(aPacket + lTrackLength);
+00000701:   812D        LDD     R18,Y+5          Load indirect with displacement
+00000702:   813E        LDD     R19,Y+6          Load indirect with displacement
+00000703:   E08E        LDI     R24,0x0E         Load immediate
+00000704:   E091        LDI     R25,0x01         Load immediate
+00000705:   9F28        MUL     R18,R24          Multiply unsigned
+00000706:   01A0        MOVW    R20,R0           Copy register pair
+00000707:   9F29        MUL     R18,R25          Multiply unsigned
+00000708:   0D50        ADD     R21,R0           Add without carry
+00000709:   9F38        MUL     R19,R24          Multiply unsigned
+0000070A:   0D50        ADD     R21,R0           Add without carry
+0000070B:   2411        CLR     R1               Clear Register
+0000070C:   019A        MOVW    R18,R20          Copy register pair
+0000070D:   8189        LDD     R24,Y+1          Load indirect with displacement
+0000070E:   819A        LDD     R25,Y+2          Load indirect with displacement
+0000070F:   0F82        ADD     R24,R18          Add without carry
+00000710:   1F93        ADC     R25,R19          Add with carry
+00000711:   8798        STD     Y+8,R25          Store indirect with displacement
+00000712:   838F        STD     Y+7,R24          Store indirect with displacement

================================================================================

478:      	uint16_t lRealLength = 0;
+000006FB:   821C        STD     Y+4,R1           Store indirect with displacement
+000006FC:   821B        STD     Y+3,R1           Store indirect with displacement
479:      	uint16_t lTrackLength = 1;
+000006FD:   E081        LDI     R24,0x01         Load immediate
+000006FE:   E090        LDI     R25,0x00         Load immediate
+000006FF:   839E        STD     Y+6,R25          Store indirect with displacement
+00000700:   838D        STD     Y+5,R24          Store indirect with displacement
480:      	uint8_t* pData = (uint8_t *)aPacket;
+00000701:   8189        LDD     R24,Y+1          Load indirect with displacement
+00000702:   819A        LDD     R25,Y+2          Load indirect with displacement
+00000703:   8798        STD     Y+8,R25          Store indirect with displacement
+00000704:   838F        STD     Y+7,R24          Store indirect with displacement
481:      	pData += lTrackLength;
+00000705:   812F        LDD     R18,Y+7          Load indirect with displacement
+00000706:   8538        LDD     R19,Y+8          Load indirect with displacement
+00000707:   818D        LDD     R24,Y+5          Load indirect with displacement
+00000708:   819E        LDD     R25,Y+6          Load indirect with displacement
+00000709:   0F82        ADD     R24,R18          Add without carry
+0000070A:   1F93        ADC     R25,R19          Add with carry
+0000070B:   8798        STD     Y+8,R25          Store indirect with displacement
+0000070C:   838F        STD     Y+7,R24          Store indirect with displacement

Now, as far as I'm concerned pData = (uint8_t*)(aPacket + lTrackLength);
should result in the correct pointer value. The actual data is aPacket=0x015F and lTrackLength being on the stack at location 0x10F0 initialised with a value of 1. In my opinion pData should be initalised with the value 0x0160 which is aPacket + lTrackLength.

However, the result of this code, as seen above in assemler results in pData getting a value 0x02CD?

The bits that confuse me are the immediate loading and multiplies? I can't understand what they're there for.

The second section of the disassembly above works fine and does exactly what I expected the first line to do. I'm sure I've done pointer arthmitic like this before and its been fine.

Has anyone got any ideas as to whether my c statement should result okay, or can anyone decipher what the compiler is trying to do in the first case?

I'm using avr-gcc 3.4.6 and optimisation is set to 0 because I'm debugging. Any help greatly appreciated.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You didn't show the declaration of "aPacket", but my guess is that it looks something like
"struct of_size_0x16E *aPacket".

Try:

uint8_t* pData = (uint8_t *)aPacket + lTrackLength;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, sorry, the aStructure argument is of type:

struct structure* aPacket

hence the cast to uint8_t*

Here's the c:

void BnetRespond(struct strBnetPacket* aPacket)
{
	uint16_t lRealLength = 0;
	uint16_t lTrackLength = 1;
	uint8_t* pData = (uint8_t *)(aPacket + lTrackLength);

Anyway, that works when it's not in the parenthesis. I'm still unsure why though! Had a quick check through the rest of my code and I seem to stick with the ((uint8_t *)aPacket + lTrackLength) convention, so my brain must be a bit fried. I still think the first statement should do the same.

Thanks for the quick response.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, K&R to the rescue.

Pointer arithmitic :

(uint8_t*)(aPacket + lTrackLength);

Means to point at aPacket + 1 x sizeof_aPacket and NOT to add one byte, hence the compiler is working out the address of the data element immediately after aPacket. The cast is only working on the result of the pointer addition.

Hence:

(uint8_t*)aPacket + lTrackLength;
or
((uint8_t*)aPacket + lTrackLength);

evalutates by casting aPacket as a pointer of type uint8_t* so that when we add to it, we add a number of bytes offset, not a number of multiples of the sizeof aPacket.

Glad I have refreshed that one in my mind! Thanks for the pointers!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The two are not equivalent. With pointer arithmetic, it will add lTrackLength times the size of what the pointer points to. With the parenthesis the pointer points to a structure (of whatever size), so lTrackLenth * sizeof(aPacket) is added. Without the parenthesis, the pointer to the structure is coerced to a pointer to a uint8_t first, so lTrackLength * sizeof(uint8_t) is added.

Regards,
Steve A.

The Board helps those that help themselves.