2

I am not quite sure whether it is impossible to print a compicated-macro value at compilation time in C language. My macro is Like below:

#define ADDR_START1        0x0001
#define SIZE1              0x1000 
#define ADDR_START2        START1 + SIZE1
#define SIZE2              0x2000 
#define ADDR_START3        START2 + SIZE2
#define SIZE3              0x3000
#define ADDR_RESERVED      0xFFFF - (ADDR_START3 + SIZE3)

Now, in order to get to know the remaining address size at compilation time, how can I print the value of "ADDR_RESERVED"? If the value is unavailable, is it because any calculation process cannot be done during compilation time?

Perlman Soong
  • 111
  • 1
  • 9
  • Printing the value may be difficult, but you can conditionally abort compilation using `#if` and `#error` directives. – MikeCAT Mar 13 '23 at 13:53
  • 1
    Does this answer your question? [How do I show the value of a #define at compile-time?](https://stackoverflow.com/questions/1562074/how-do-i-show-the-value-of-a-define-at-compile-time) – mnistic Mar 13 '23 at 14:32
  • @mnistic: No, that is for a situation that involves mere macro replacement, not arithmetic. – Eric Postpischil Mar 13 '23 at 15:08
  • A way to do this with GCC and Clang is to use the macro in an `asm` construct as the value of an “immediate” operand, which puts its value into the assembly source code. Then compile with the `-S` option to generate the assembly code and use `grep` or a similar tool to extract the line. There is some information about that [here](https://stackoverflow.com/questions/47334646/including-a-header-file-in-a-s-to-get-some-struct-size/47339218#47339218), although there may be better answers. – Eric Postpischil Mar 13 '23 at 15:09
  • I am usually using solution from [this question](https://stackoverflow.com/questions/20979565/how-can-i-print-the-result-of-sizeof-at-compile-time-in-c), if it is about some numerical value. – Eugene Sh. Mar 13 '23 at 16:15
  • 1
    Modern IDEs can expand macros. This includes everything Clangd-based (e.g. VSC with Clangd extension) and the latest VS too. – HolyBlackCat Mar 13 '23 at 19:45

3 Answers3

1

The language doesn't provide a way to see the intermediate output of the preprocessor, but the compiler might. For instance, for gcc, the -E flag tells it to just run the preprocessor. This will result in a few billion lines of extraneous output from the header files, so you'll probably want to filter those out.

For gcc, this will do the trick (for a source file named "filename.c"):

gcc -dI -E filename.c | awk '/^# /{skip=1} !skip{print} /^# .*"filename.c"/{skip=0}'

In addition to the -E flag, we pass -dI, which leaves the #include lines in place (in addition to expanding them). The awk command then filters out everything that doesn't come from "filename.c". It won't actually do arithmetic, since it's the compiler that handles that step, but it'll expand everything.

$ cat filename.c
#include <stdio.h>

#define F(A,B) A+B

F(32,10)

$ gcc -dI -E filename.c | awk '/^# /{skip=1} !skip{print} /^# .*"filename.c"/{skip=0}'
#include <stdio.h>



32+10
Ray
  • 1,706
  • 22
  • 30
0

According to MikeCAT's suggestion I tried the testing code below and it works fine:

#if ADDR_RESERVED < 0
#error "no remaining space..."
#endif

Despite no value being printed, the solution solved my needs.

Perlman Soong
  • 111
  • 1
  • 9
0
admittedly, this is ultra brute force :

 echo '

#define ADDR_START1        0x0001
#define SIZE1              0x1000
#define ADDR_START2        START1 + SIZE1
#define SIZE2              0x2000
#define ADDR_START3        START2 + SIZE2
#define SIZE3              0x3000
#define ADDR_RESERVED      0xFFFF - (ADDR_START3 + SIZE3)' |
mawk 'BEGIN { FS="(^[#]define)?[() \t]+"
              RS="[ \t]*\n[ \t]*" 
} sub("^", sprintf("%16d ", 5 < NF \
? +$3 + (-1)^("-"==$4) * (__[$5] + (-1)^("-"==$6) + __[$7]) \
: __[$2]=__[substr($2, index($2,"_")+1)]= NF==3              \
                  ? +$3 : __[$3] + (-1)^("-"==$4) * __[$5]))^_' 
               1 #define ADDR_START1        0x0001
            4096 #define SIZE1              0x1000
            4097 #define ADDR_START2        START1 + SIZE1
            8192 #define SIZE2              0x2000
           12289 #define ADDR_START3        START2 + SIZE2
           12288 #define SIZE3              0x3000
           40957 #define ADDR_RESERVED      0xFFFF - (ADDR_START3 + SIZE3)

and the hex-version matches expectations :

 0x               1 #define ADDR_START1        0x0001
 0x            1000 #define SIZE1              0x1000
 0x            1001 #define ADDR_START2        START1 + SIZE1
 0x            2000 #define SIZE2              0x2000
 0x            3001 #define ADDR_START3        START2 + SIZE2
 0x            3000 #define SIZE3              0x3000
 0x            9FFD #define ADDR_RESERVED      0xFFFF - (ADDR_START3 + SIZE3)

it's "algorithmic" in the sense it's actually reading variable values and doing math on them, but it's also brute force for hard-coding in the parenthesis and not having any ability to parse nested algebraic expressions

RARE Kpop Manifesto
  • 2,453
  • 3
  • 11