warning: cast to pointer from integer of different size

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

The code below generates this warning:

Quote:

warning: cast to pointer from integer of different size

and I don't really understand why.
Can somebody please explain why?
The offending line is "Content = *((uint8_t*)Reg);

static uint8_t HandlePacket(TPacket *pMsg)
{
	char *pCursor;
	uint8_t Content;
	uint8_t Reg;

 ... 

	switch( *pCursor)
	{
	case '>':
		pCursor++;
		switch( *pCursor)
		{
		case 'r':
			MsgOut.Data[0] = 'r';
			pCursor++;
			Reg = GetUint32( &pCursor, 6 );
			ItoaF( MsgOut.Data + 1, Reg, 4, 16);
			MsgOut.Data[5] = '=';

			// Reg is a number.
			// Cast it into a pointer to a register adress.
			// Take the contents of that register.
			// Cast the contents of that register to a uint8_t.
			Content = *((uint8_t*)Reg);
			ItoaF( MsgOut.Data + 6, Content, 4, 16);	// Implicit uint8_t to uint32_t conversion.
			PacketSize = 10;
			break;
		}
		break;

A bit more background information:
Using: avr-gcc (GCC) 4.5.3
This code is meant for debugging.
My intent is to send an ascii string packed in a network packet (over uart/rs485). The avr decode's de commands and executes them en encodes the result again in another ascii string. Not the most efficient way of debugging, but most of the code already was in my project.

If I request the contents of 0x4c (TCNT1L) I get a different value each time, but the contents of the temporary register 0x4d (TCNT1H) only change after I've read TCNT1L. Other registers also seem to have plausible values.

Is this a search in the right direction?

Quote:
paul@dualcore /usr/lib/avr/include/avr $ grep -nR "define _SFR_IO8" *.h
iom128rfa1.h:54:# define _SFR_IO8_STRUCT(io_addr,type) _MMIO_BYTE_STRUCT((io_addr) + 0x20, type)
sfr_defs.h:152:#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
sfr_defs.h:179:#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

The compiler is telling you that you told it to do something strange.
The compiler is doing it anyway.
From your comments, the compiler is doing exactly what you want.
If silencing the warning is important, cast to uint16_t before casting to pointer.

Iluvatar is the better part of Valar.

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

Pointers are 16 bits wirde but you are using a 32-bit value like a pointer. That's worth a warning because 16 bits will be lost.

avrfreaks does not support Opera. Profile inactive.

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

Other way round: Reg is only 8 bits. That does not comprise a sensible pointer. Sorry for misreading, got confused by the GetUint32.

avrfreaks does not support Opera. Profile inactive.

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

And what does GetUint32() return? If it really returns a pointer, then why is not Reg defined as a pointer?

Regards,
Steve A.

The Board helps those that help themselves.

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

Paulvdh wrote:
This is better:

	uint16_t Reg;
	Content = *(uint8_t*)Reg;

'Tain't.
To possibly be better, there should be a comment to the effect that you altered the type of an 8-bit variable to inhibit a warning.
Without such a comment, your successors, e.g. yourself, might be confused.

Iluvatar is the better part of Valar.

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

Pointers in avr-gcc being 16-bit is one thing; this

Paulvdh wrote:
If I request the contents of 0x4c (TCNT1L) I get a different value each time, but the contents of the temporary register 0x4d (TCNT1H) only change after I've read TCNT1L.
is another: there are 16-bit SFRs in AVR which are to be read out bytewise in a specific order. There is an intermediate (directly unaccessible) register involved. Read thoroughly the relevant parts of manual to avoid surprises.

JW

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

Quote:

This generates 4 opcodes, but I think it can be done with 2 because the two opcodes in the middle use the same tmp register for the same value.

What are you talking about? To transfer two bytes from one place to another is always going to be two byte reads and two byte writes. That's 4 opcodes in AVR(8) land.

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

Quote:

all use the same temp register,

Internally! It's for double-buffering. It's not user accessible.

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

Quote:
GetUint32() returns an uint32_t
Then how do you expect to put a uint32_t into a uint8_t and expect no loss of data? And why on Earth would you then treat that 8 bit value as a pointer?

Regards,
Steve A.

The Board helps those that help themselves.

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

Quote:
It's easy, just take control of the input into an existing function which is also able to handle bigger numbers for other purposes.
If it was so "easy", then why did you do it in a way that had absolutely no way of working?

Regards,
Steve A.

The Board helps those that help themselves.

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

But that code did not work, except maybe by chance in some circumstances. 8 bits can simply not hold a 16 bit address.

Regards,
Steve A.

The Board helps those that help themselves.

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

But pointers in C are always at least 16 bits no matter what they point to.

Regards,
Steve A.

The Board helps those that help themselves.