gustavovelascoh
gustavovelascoh

Reputation: 1228

Why is this showing "Invalid type conversion"?

I have this piece of C code (For MSP430 platforms, cl430 compiler):

void function(uint8_t * x){
    // This variable is defined in the linker file as "X_ADDR = 0xE000;"
    extern uint32_t X_ADDR; 
    uint16_t i = 0;
    uint16_t size = 10;
    uint32_t dst_addr = (uint32_t) &X_ADDR; 

    for (i=0; i < size; i++){
         *((uint8_t *) (dst_addr+i)) = *(x+i); // <-- This line shows the warning
}

What I understand is this, but here is where I guess I am wrong:

*((uint8_t *) (dst_addr+i)) = *(x + i);
                |       |       |   |
                V       V       V   V
*((uint8_t *) (u32  + u16)) = *(u8*+u16);
       *((uint8_t *) (u32)) = *(u8*);
                     *(u8*) = u8;
                         u8 = u8;

This platform is 16-bits but it supports an extended addressing mode of 20-bits.

Any hint on this? and how should it be done instead? Thanks in advance

Upvotes: 1

Views: 8961

Answers (3)

CL.
CL.

Reputation: 180161

You are converting a 32-bit integer into a 16-bit pointer.

To ensure that your integer type has the same size as a pointer, use uintptr_t from <stdint.h>.


And when you treating X_ADDR as a byte array, it would be a better idea to declare it as such:

extern uint8_t X_ADDR[];

X_ADDR[i] = ...;

Upvotes: 0

Lundin
Lundin

Reputation: 214187

You seem to get this on 64 bit compilers that use 64 bit pointers. Converting a 32 bit integer to a 64 bit pointer is questionable and non-portable.

Correct this by using the portable integer type meant to be used for this very purpose:

uintptr_t dst_addr = 0x00FFABCD; 

Now it will compile cleanly on all mainstream 64 bit compilers. Tried on gcc, clang icc with -std=c11 -Wextra -Wall -pedantic-errors, no problems.

In addition, when accessing an absolute address, you will almost certainly need to volatile qualify the pointer.

Upvotes: 4

Steve Friedl
Steve Friedl

Reputation: 4247

It's objecting to the conversion of the integer dst_addr to a pointer, not the assignment of the uint8_t

$ gcc -c -Wall -W type.c
type.c: In function 'function':
type.c:11:12: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
          *((uint8_t *) (dst_addr+i)) = *(x+i); // <-- This line shows the warning
            ^

and clang offers similar:

$ clang -c type.c -W -Wall
type.c:11:12: warning: cast to 'uint8_t *' (aka 'unsigned char *') from smaller integer type 'unsigned int'
      [-Wint-to-pointer-cast]
         *((uint8_t *) (dst_addr+i)) = *(x+i); // <-- This line shows the warning
           ^

(clang 3.4.2; gcc 4.8.5)

Converting from an int to a pointer is always suspect, and I'm not sure there's a way to tell the compiler that you really meant it, at least if you turn on all the warnings (which is a good practice).

Upvotes: 0

Related Questions