cc-preprocessorprimitive-types

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.


Solution

  • 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
    

    This works:

    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.