1

I've made some macro to help me design a dialog's widget, in a gcc project. But I'm getting compilation errors, so I made the following test :

#define XPOS_ISAFTER(obj) (obj##_XPOS + obj##_XSIZE)

#define PMD_TUTU_XPOS 10
#define PMD_TUTU_XSIZE 10

#define PMD_TUTU2_XPOS  XPOS_ISAFTER(PMD_TUTU)
#define PMD_TUTU2_XSIZE 20

#define PMD_TUTU3_XPOS  XPOS_ISAFTER(PMD_TUTU2)


int main(void){
int i = 0;
    printf("Hello World!\n");
    fflush(stdout);

      /* Infinite loop */
      while (1)
      {
          i += PMD_TUTU2_XPOS;
          i += PMD_TUTU3_XPOS;
      }

    return 0;
}

When asking for preprocessor output I get the following :

839 int main(void){
840     int i = 0;
841         printf("Hello World!\n");
842             fflush(stdout);
843
844
845                   while (1)
846                           {
847                                       i += (10 + 10);
848                                       i += (XPOS_ISAFTER(PMD_TUTU) + 20);
849                                                   }
850
851                     return 0;

I have search some advices tricks to force rescan, without any result. So the pre-processor do not expand this recursive macro ?

2 Answers2

1

The problem is not that the preprocessor fails to rescan, but rather that when it does, it refuses to expand the appearance of the XPOS_IS_AFTER() macro in text resulting (indirectly) from a previous expansion of that same macro. In other words, the preprocessor does not support macro recursion. This is explicitly specified by the standard:

[When rescanning a macro's replacement text,] If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file's preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

(C2011, 6.10.3.4/2 )

GCC does exactly what it should with your code. You'll need a different plan.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • That is right. I finally found another [question](https://stackoverflow.com/questions/12447557/can-we-have-recursive-macros) with similar answers as yours. I may try the workaround from [Paul Fultz](https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms#deferred-expression) – Selso Liberado Feb 07 '18 at 20:55
0

After reading the prep-processor tricks from Paul F, and many tries I concluded that it was not appliable to my case because I don't explicitely write a recursive macro, as it seems to be the case in the workaround I read.

So I write some macro less efficient where I avoid the recursion :

#define XPOS_ISAFTER(obj) ( obj##_XPOS + obj##_XSIZE )
#define XPOS_ISAFTER2(obj1,obj2) (XPOS_ISAFTER(obj1) + obj2##_XSIZE)
#define XPOS_ISAFTER3(obj1,obj2, obj3) (XPOS_ISAFTER2(obj1, obj2) + obj3##_XSIZE)


#define YPOS_ISUNDER(obj) ( obj##_YPOS +  obj##_YSIZE )
#define YPOS_ISUNDER2(obj1,obj2) ( YPOS_ISUNDER(obj1) + obj2##_YSIZE )
#define YPOS_ISUNDER3(obj1, obj2, obj3) ( YPOS_ISUNDER2(obj1,obj2) + obj3##_YSIZE )
#define YPOS_ISUNDER4(obj1,obj2, obj3, obj4) ( YPOS_ISUNDER3(obj1,obj2, obj3) + obj4##_YSIZE )