Shahbaz Shahbaz - 1 month ago 9
C Question

Remove cast from constant in preprocessor

Background



In a microcontroller code, I am using a library provided by the producer where there are many constants defined. I'm trying to give an error if there's a mismatch between some of my constants (shared with components outside the microcontroller, with
git-subtree
) and the microcontroller constants.

For example, the library defines:

#ifdef SOME_PARTICULAR_MODEL
#define FLASH_BLOCK_SIZE ((uint8_t)64)
/* else, other models */
#endif


And somewhere, in a header shared between the microcontroller code and some code compiled on the PC, I have for example:

#define MYPROG_BLOCK_SIZE 64


And to make sure these constants match, in the microcontroller code, where both constants exist, I have:

#if MYPROG_BLOCK_SIZE != FLASH_BLOCK_SIZE
#error "mismatch between actual block size and defined block size"
#endif


This is to make sure if the code is ever ported to a bigger microcontroller, the shared header would also be updated.

The Problem



The problem is that this gets reduced to:

#if 64 != ((uint8_t)64)


which I'm not sure if is valid C, but nonetheless makes the compiler choke up. Testing, I found out that the problem is not that
uint8_t
is a typedef and it still chokes up with a cast to
int
for example.

The Question



Is there a way to remove the
(uint8_t)
part from a value defined as
((uint8_t)64)
? If not, is there any way to change it so the expression turns into one without a cast?

I thought about defining
uint8_t
as something and undefining it after the
#if
, but I can't figure out how I can avoid the cast nature of
(Y)X
and turn it into an arithmetic expression.

Answer

Here is an improved version (the first version is below). This one does not depend on the cast being uint8_t; it will work with any FLASH_BLOCK_SIZE replacement list of the form ((some type) number).

#define MYPROG_BLOCK_SIZE   64
#define FLASH_BLOCK_SIZE    ((uint8_t)64)

#define B(x)
#define C(x)    B x
#define D(x)    C x

#if MYPROG_BLOCK_SIZE != D(FLASH_BLOCK_SIZE)
    #error "mismatch between actual block size and defined block size"
#endif

Here is the original version:

#define MYPROG_BLOCK_SIZE  64
#define FLASH_BLOCK_SIZE   ((uint8_t)64)

#define uint8_t             
#define Helper(x)          x
#define Deparenthesize(x)  Helper x

#if MYPROG_BLOCK_SIZE != Deparenthesize(Deparenthesize(FLASH_BLOCK_SIZE))
    #error "mismatch between actual block size and defined block size"
#endif
#undef uint8_t

When writing code, I would prefer a static assert, but the above does what you requested in the preprocessor.

Comments