Horkyze
Horkyze

Reputation: 359

What does this C macro mean?

Looking at fm_transmitter source code, I came across this macro, which is used quite often.

#define ACCESS(base, offset) *(volatile unsigned*)((int)base + offset)

I guess its a sum of base and offset casted as int, then re-casted into unsigned pointer and then again pointer?

Upvotes: 2

Views: 165

Answers (1)

This macro provides access to an offset that is measured in bytes. You could rewrite it as

#define ACCESS(base, offset) *(volatile unsigned*)&((char*)base)[offset]

only that the original version does the arithmetic via the int type instead of the char* type.

Note that use of this macro likely invokes undefined behavior: The resulting pointer is not guaranteed to be properly aligned, and if the data was written as some other type than an int variant, it's a violation of strict aliasing rules as well.

Also, the choice of int to do the pointer arithmetic is a very poor choice, the calculation should at least be done via size_t or uintptr_t to guarantee that the pointer is not truncated during the cast to the integer type. My rewritten version does not have this specific problem, however, the danger of undefined behavior remains with both versions.

Finally, as Olaf rightly noted in the comments, it's also a bad idea to cast to volatile unsigned* since the width of this type is implementation defined. A cast to volatile uint32_t* would likely be more appropriate for communication with hardware.

Upvotes: 4

Related Questions