24

I am writing and reading registers from a memory map, like this:

//READ
return *((volatile uint32_t *) ( map + offset ));

//WRITE
*((volatile uint32_t *) ( map + offset )) = value;

However the compiler gives me warnings like this:

warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]

How can I change my code to remove the warnings? I am using C++ and Linux.

user1876942
  • 1,411
  • 2
  • 20
  • 32

3 Answers3

29

Since void* is a pointer to an unknown type you can't do pointer arithmetic on it, as the compiler wouldn't know how big the thing pointed to is.

Your best bet is to cast map to a type that is a byte wide and then do the arithmetic. You can use uint8_t for this:

//READ
return *((volatile uint32_t *) ( ((uint8_t*)map) + offset ));

//WRITE
*((volatile uint32_t *) ( ((uint8_t*)map)+ offset )) = value;
adlr0
  • 758
  • 9
  • 13
Sean
  • 60,939
  • 11
  • 97
  • 136
  • but void * is a well known type, it's an address type, it can point to any address type... I guess the solution is to static cast it to uintptr_t *, then – Dmytro Nov 09 '16 at 01:25
  • 3
    It would be more idiomatic to cast to `char`, as `sizeof(char)` is defined to be 1. – Artyer Jul 09 '17 at 19:59
  • @Artyer `uint8_t` is much more preferred and guaranteed to have a size of 1 byte. – VP. May 22 '19 at 13:43
  • @VictorPolevoy Only `uint_least8_t` is guaranteed to have a size of 1 byte, as `uint8_t` is not guaranteed to exist (I know this will never happen in practice, but still). Also, `uint8_t` means "8 bit number", and `char` means "byte", and `offset` is a byte offset. – Artyer May 22 '19 at 17:41
  • @Artyer uh, I have never known about `uint_least8_t`, thank you. But I have always been thinking of `char` as a "character" and of `uint8_t` as a "byte", was I wrong all the time? :) Also, coming back to C++ from Rust that sounds really weird, that `uint8_t` is not guaranteed to exist :) – VP. May 23 '19 at 06:55
8

Type void is incomplete type. Its size is unknown. So the pointer arithmetic with pointers to void has no sense. You have to cast the pointer to type void to a pointer of some other type for example to pointer to char. Also take into account that you may not assign an object declared with qualifier volatile.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
3

If the use of arithmetic on void pointers is really what you want as it is made possible by GCC (see Arithmetic on void- and Function-Pointers) you can use -Wno-pointer-arith to suppress the warning.

Damien
  • 164
  • 11