0

is there a way I can achieve this

#define MAC(VAL , num)
#ifndef VAL \
int #VAL = num ; \
#define VAL \
#else \
#VAL = num ; \
#endif \

I want to define VAL only once

Kumaran Ida
  • 39
  • 2
  • 9
  • 1
    You can't use `#ifdef`, `#define` or any other preprocessor `#` directives inside a macro. Why do you need it inside the macro anyway, if you want it just once? – Eugene Sh. May 24 '16 at 15:03
  • 5
    http://stackoverflow.com/questions/2831934/c-preprocessor-using-if-inside-define – sabbahillel May 24 '16 at 15:07
  • @sabbahillel: i didn't find any valid answer , the problem here is VAL can't be anything , solution provided in that thread will work only if VAL is known in advance – Kumaran Ida May 24 '16 at 15:13
  • @EugeneSh.: i am not getting your question , the macro MAC can we used in multiple files and the intention is to define VAL if it is not defined else just assign the value – Kumaran Ida May 24 '16 at 15:15
  • 1
    *I want to define VAL only once*. Do you realize that using a preprocessor macro for defining a variable will be a problem when your program spans multiple compilation units? – R Sahu May 24 '16 at 15:18
  • @RSahu: But due to some reason i need to somehow do that and that's why looking for some solution , i know it's bad . but it's an infra , we can't ask ppl to manually check and define if not define , it will be really helpful if there is some smarter way – Kumaran Ida May 24 '16 at 15:21
  • Would `const static int VAL = num;` work? – Raymond Chen May 25 '16 at 05:38
  • it will throw compilation time error – Kumaran Ida May 25 '16 at 08:27
  • Please make a MCVE stackoverflow.com/help/mcve In this case it involves several files or lines of code in which the macro should be useable and the desired output after preprocessing. I am pretty sure that with that info I can propose a solution, based on an `#if` outside the macro definition. – Yunnosch Apr 09 '17 at 11:20
  • What are `int #VAL = num ;` and `#VAL = num ;` supposed to achieve? They should be understood by the compiler after preprocessing. I doubt they will be. – Yunnosch Apr 09 '17 at 11:23

1 Answers1

0

The answer is not "No", I do not dare to say something is impossible with macro-magic.
But the answer is "Do not try." because ... see comment by RSahu.

And here is the tedious path to that answer.
The closest I got (for VAL=MyInt and num=5) is:

#ifndef MyInt_flag
#define MyInt_flag
int
#endif
MyInt 5 = 5;

Note that there is (OK, I did find) no way of using any kind of macro to actually use VAL and num abstractly. The reasons for that you will find below as "tree of failed attempts and workarounds". Everybody is invited to find even one slightly more elegant workaround for any of the problems I faced. If this gets good I will make this a wiki.

If above is the nearest solution to what you want, it is very important to read and think through the extremely valuable comment by @RSahu.

I rephrase it, to provide a different view point:
If you actually manage to achieve what you try, then you will have extremely ugly problems when doing this in more than one code file.
The goal to only define a variable once across several code files can only be achieved by agreeing on a single one to define it and use only external references to that one from the other code files.
That is because compiler and preprocessor are unaware of the content of other code files.
Any macros defined in one code (or headers it includes) are unknown in others.
Only the linker is (indirectly) aware of C-language definitions in all code files.
And it is the linker who will give you the errors (or worse, silent behaviour) you will not like in the end.
End of generoursly rephrasing @RSahu.

And, as even another view point, a summary:
You will have bigger and uglier problems with this concept than with clean design of which variable gets defined where.

Stop reading here, seriously.

tree of failed attempts and workarounds

I tried hard to get as close as possible to the desired solution.

/* #define MAC(VAL, num) Does not work
   ... because you want to define a flag-macro 
       for keeping track of is-already-defined for each variable */

/* In order to use #define etc. inside the solution,  
   it needs to be in a header which gets included. 
   The following two "#define"s provide the quasi-parameters
   VAL and num. This is needed before each use of said header. */
#define VAL MyInt
#define num  5

/* Imagine the rest of the solution below to be inside the
   header "theheader.h". And do the corresponding
#include "theheader.h"
 */

#define VARFLAG(parVarId) parVarId##_flag
/* Just to deomstrate: */ char VARFLAG(VAL);
/*
#ifndef VARFLAG(VAL)
   This fails with "warning: extra tokens at end of #ifndef directive"
#define VARFLAG(VAL)
#endif
You cannot test the definition of a parameterized macro.
 */

#ifndef VARFLAG
0;
#else
1;
/* This is the preprocessed result. 
   It does not have any dependency to VAL.
   It just indicates, that a definition for VARFLAG
   exists,
   in this case for parameterized VARFLAG(parVarId).
 */
#endif

#ifdef VAL
2;
/* This is the preprocessed result.
   No surprise, because the quasi-parameter is (should be defined
   just before including "theheader.h"
 */
#else
3;
#endif

/* So lets skip using VAL and try the actual parameter "MyInt"
   for the formal quasi-parameter VAL. */
#ifdef MyInt
4;
#else
5;
/* This is the preprocessed result,  
   becaue there is no macro of this name,
   which at this point only happens to be a C-variable name,
   unknown to the preprocessor.
   You do not want to "just" define MyInt, i.e. without a body,
   because that would kill all later attempts to use the variable.
   I.e. do not do
   #define MyInt
 */
#endif

#ifdef MyInt_flag
6;
#else /* of #ifdef MyInt_flag */
7;
/* This is the preprocessed result,
   because there also is no macro of this name.
   We will make sure later, that when MyInt gets defined
   as a C-variable, MyInt_flag gets defined as a macro.
 */
/* Now define MyInt, using quasi-parameter VAL */ 
int VAL = num;
/* Preprocessed result is 
int MyInt = 5;
 */ 

#ifdef MyInt
8;
#else
9;
/* This is the preprocessed result,
   because only the C-variable exists, not the macro.
 */
#endif

 /* Attempting to define MyInt_flag, using
#define VARFLAG(MyInt)
    fails with a 'warning: "VARFLAG" redefined#.
    So we have to do it the non-parameterized way.
    Sorry, this is the first of the things that 
    are not possible more conveniently.
  */
#define MyInt_flag 
#endif /* of #ifdef MyInt_flag #else ... */

/* Double-check, 
sadly still not possible via
#ifdef VARFLAG(VAL)
neither via
#ifdef VARFLAG(MyInt)
so it has to be */
#ifdef MyInt_flag
10;
/* This at least is the preprocessed result,
   because now there is a macro named "MyInt_flag".
 */
#else
11;
#endif

/* Now we can simulate the case of using "theheader.h"
   in case the variable already is defined. */
#ifndef MyInt_flag
12;
/* representing all of above again, 
   but does not happen,
   because the macro flag and the reflected C-variable
   ARE defined */
#else
VAL = num;
13;
#endif

Output (gcc -E -P toy.c):

1;
2;
5;
7;
int MyInt = 5;
9;
10;
MyInt = 5;
13;
Yunnosch
  • 26,130
  • 9
  • 42
  • 54