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
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
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.
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;