0

Judging by this Print numeric value of a define that's based on other macros via pragma message? , what I want is likely not possible; then again, I'm not doing arithmetic here - so here is my example:

#include <stdio.h>
enum my_sizes { SIZE_BITS_8 = 0, SIZE_BITS_16 = 1, SIZE_BITS_32 = 2 };

#define XSTR(x) STR(x)
#define STR(x) #x

#define CHOSEN_SIZE_BITS SIZE_BITS_32
#define CHOSEN_SIZE_BYTES \
    ( CHOSEN_SIZE_BITS==SIZE_BITS_8 ? 1  \
      : CHOSEN_SIZE_BITS==SIZE_BITS_16 ? 2 \
      : CHOSEN_SIZE_BITS==SIZE_BITS_32 ? 4 \
      : 0 )

#pragma message( "CHOSEN_SIZE_BITS " XSTR(CHOSEN_SIZE_BITS) " CHOSEN_SIZE_BYTES " XSTR(CHOSEN_SIZE_BYTES) )

int main() {
    printf("Hello, world! bytes: %d!\r\n", CHOSEN_SIZE_BYTES);
    return 0;
}

In https://replit.com/languages/c, this produces:

> clang-7 -pthread -lm -o main main.c
main.c:14:9: warning: CHOSEN_SIZE_BITS SIZE_BITS_32
      CHOSEN_SIZE_BYTES ( SIZE_BITS_32==SIZE_BITS_8 ? 1 :
      SIZE_BITS_32==SIZE_BITS_16 ? 2 :
      SIZE_BITS_32==SIZE_BITS_32 ? 4 : 0 )
      [-W#pragma-messages]
#pragma message( "CHOSEN_SIZE_BITS " XSTR(CHOSEN_SIZE_...
        ^
1 warning generated.
> ./main
Hello, world! bytes: 4!
> 

What I wanted instead, was the printout of pragma message to be:

main.c:14:9: warning: CHOSEN_SIZE_BITS 2 CHOSEN_SIZE_BYTES 4

Note that XSTR would have expanded CHOSEN_SIZE_BITS to a number, in case it was defined via #define CHOSEN_SIZE_BITS 2, but it seemingly doesn't if an enum value is used in the define; and of course, the whole ternary expression is included in the pragma message printout - even if the C printout (via printf) confirms that the CHOSEN_SIZE_BYTES does indeed end up with the expected value 4.

So, is it somehow possible to get the printout that I want from the above macros - and if so, how?

sdbbs
  • 4,270
  • 5
  • 32
  • 87
  • 1
    Ternary is something evaulated at runtime. You would have to implement ternary at compile time in preprocessor using expansions. `enum my_sizes { SIZE_BITS_8` those are runtime values, not macro definitions. `is it somehow possible` How much of the code are you willing to change? Are you willing to make `my_sizes` macros? – KamilCuk Sep 08 '22 at 20:12

1 Answers1

1

To calculate something in preprocessor you have to calculate it in preprocessor. Ternary is evaluated at runtime. In preprocessor you have macro expansions and ## operator and then some more macro expansions and ## operator. Nothing more.

The following code:

#define SIZE_BITS_8   0
#define SIZE_BITS_16  1
#define SIZE_BITS_32  2

#define XSTR(x) STR(x)
#define STR(x) #x

#define BITS_TO_BYTE_0()  1
#define BITS_TO_BYTE_1()  2
#define BITS_TO_BYTE_2()  4
#define BITS_TO_BYTE_IN(SIZE_BITS)  \
        BITS_TO_BYTE_##SIZE_BITS()
#define BITS_TO_BYTE(SIZE_BITS)  \
        BITS_TO_BYTE_IN(SIZE_BITS)


#define CHOSEN_SIZE_BITS   SIZE_BITS_32
#define CHOSEN_SIZE_BYTES  BITS_TO_BYTE(CHOSEN_SIZE_BITS)

#pragma message( "CHOSEN_SIZE_BITS " XSTR(CHOSEN_SIZE_BITS) " CHOSEN_SIZE_BYTES " XSTR(CHOSEN_SIZE_BYTES) )

Outputs the following diagnostic on GCC:

<source>:22:9: note: '#pragma message: CHOSEN_SIZE_BITS 2 CHOSEN_SIZE_BYTES 4'
   22 | #pragma message( "CHOSEN_SIZE_BITS " XSTR(CHOSEN_SIZE_BITS) " CHOSEN_SIZE_BYTES " XSTR(CHOSEN_SIZE_BYTES) )
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • Excellent - I was unaware that ternary is evaluated at runtime, and thank you for providing an alternative that is evaluated at preprocessor time (I guess I should have been aware that `enum` values are runtime, but that also escaped me until I saw that mentioned in your comment; thanks! – sdbbs Sep 09 '22 at 09:51