1

I have two structures rom and transfer.

    typedef struct
    {
    const uint32 data;
    }rom;

    typedef struct
    {
    const rom* const read;
    }transfer;

    extern const transfer num;

In another C program I have declared

transfer* count;

and

count = (transfer*)(*((uint32*)((uint32)&num) + 2*seqno));

Above code compiles in gcc compiler. But when I include extern "C" {}, save the file as .cpp and building with g++ compiler it throws me an error. Since direct type cast is not possible with g++ compiler. the error is

error: cast from 'const transfer*' to 'uint32{{aka unsigned int}' loses precision [-fpermissive]

How could we typecast for c++ compiler?

Honeybee
  • 13
  • 4
  • 2
    The real question is why do you think it's OK to try stuffing an address of a structure into a `uint32`, adding some value to it, then trying to dereference it as a pointer to a 32-bit unsigned `int` value - and **then** treating the result as a pointer to a structure. Even *if* a pointer would always fit into a 32-bit unsigned `int` value (and it **doesn't**...), the strict aliasing violations abound. Along with being an incomprehensible mess. – Andrew Henle Jun 08 '18 at 13:08

2 Answers2

4

There's so much wrong in that line.

  • Don't use home-brewed integer types. Use stdint.h/cstdint. That is, uint32_t and not uint32. This goes for C and C++ both.
  • uint32_t or its home-brewed equivalent is not guaranteed to be able to hold the value of a pointer. This is likely the source of the compiler message. Instead you should be using uintptr_t. Which is found in stdint.h/cstdint.
    (Perhaps the issue isn't so much C versus C++, as one compiler going 64 bit addresses but not the other, or some such.)

  • *(uint32_t*)&some_struct is a strict aliasing violation in C and C++ both.
    (As it happens you could go from uint32_t to struct type if the struct contains uint32_t among its members, but not vice versa.)

    If you have no idea what strict aliasing even means, simply don't do wild pointer conversions like this, it is undefined behavior. In particular, don't do this on gcc/g++ because it tends to go nuts if you do. (Formally it has the right to go nuts as per the standard...)

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

Casting pointer to integer, doing arithmetic on that integer, and casting back to pointer is undefined behavior. This is true even for intptr_t. The only way to do pointer arithmetic is directly on the pointer.

This is because the mapping between pointer values and intptr_t values is implementation defined and is not mandated they to be the same.

dimm
  • 1,792
  • 11
  • 15
  • I don't think that's true. If you convert an integer back to a pointer, and the pointer happens to be one that points to something, or ends up being `nullptr`, the behaviour is defined. But @Lundin is the expert on this, let's see if they comment. – Bathsheba Jun 08 '18 at 13:21
  • The only thing you can rely on is casting to `intptr_t` and then casting back to pointer, without doing any arithmetic on the `intptr_r`. – dimm Jun 08 '18 at 13:23