Get define value in preprocessor time in c - c

I want to create a define using macro expansion. The crated define shall hold the value of an other define. :)
Example:
#define ONE 1
#define TWO 2
#define MACRO(x, y) ...
...
#define MACRO_1_2 3
My question is: how can I resolve / use the value of a define in macro expansion?
I have tried to use
#define TEST_MACRO_V2(x, y) TEST_MACRO_V2_"x"_"y"
, but I get the following error:
main.c:18:34: error: ‘TEST_MACRO_V2_’ undeclared (first use in this function)
#define TEST_MACRO_V2(x, y) TEST_MACRO_V2_"x"_"y"
My test code:
#include <stdio.h>
#define ONE 1
#define TWO 2
#define TEST_MACRO_V1(x, y) TEST_MACRO_V1_##x##_##y
#define TEST_MACRO_V1_ONE_TWO 3
//#define TEST_MACRO_V2(x, y) TEST_MACRO_V2_##('x')##_##('y') -> this version does not work
#define TEST_MACRO_V2(x, y) TEST_MACRO_V2_"x"_"y"
#define TEST_MACRO_V2_1_2 4
int main()
{
printf("Test Macro V1: %d\n", TEST_MACRO_V1(ONE, TWO));
printf("Test Macro V2: %d\n", TEST_MACRO_V2(ONE, TWO));
return 0;
}
Note: TEST_MACRO_V1 works fine. I need TEST_MACRO_V2.

I tried this on ideone.com:
#include <stdio.h>
#define ONE 1
#define TWO 2
#define TEST_MACRO_HELPER(x, y) TEST_MACRO_##x##_##y
#define TEST_MACRO(x, y) TEST_MACRO_HELPER(x, y)
#define TEST_MACRO_1_2 4
int main()
{
printf("Test Macro: %d\n", TEST_MACRO(ONE, TWO));
return 0;
}
Output:
Test Macro: 4

Related

How to map #define's replacement list containing space(s) to integers (IDs)?

A #define's replacement list containing no spaces can be mapped to integers (IDs):
#define ID_double 1
#define ID_float 2
#define ID_long_double 3
#define ID_(x) ID_##x
#define ID(x) ID_(x)
#define T double
T v;
int x = ID(T); /* 1 */
Now consider:
#define T long double
The code above won't compile:
<source>:3:25: error: 'ID_long' undeclared here (not in a function)
Question: is there a way to support spaces?
For example (somehow):
#define REPLACE_SPACES_TO_UNDERSCORES(x) ??
#define ID(x) ID_(REPLACE_SPACES_TO_UNDERSCORES(x))
#define T long double
T v;
int x = ID(T); /* 3 */
The same idea I had in Replace spaces with underscores in a macro? can also be used here, and the dictionary will be much more realistical in size. In the following code on the end, ID(T) is replaced by 3.
// dictionary
#define WORD_long long,
#define WORD_double double,
// ---------------------------------------------
// the classics
#define COMMA(...) ,
#define FIRST(a, ...) a
// apply function f for each argument recursively with tail
#define FOREACHTAIL_1(f,a) f(a,)
#define FOREACHTAIL_2(f,a,...) f(a,FOREACHTAIL_1(f,__VA_ARGS__))
#define FOREACHTAIL_3(f,a,...) f(a,FOREACHTAIL_2(f,__VA_ARGS__))
#define FOREACHTAIL_4(f,a,...) f(a,FOREACHTAIL_3(f,__VA_ARGS__))
#define FOREACHTAIL_N(_4,_3,_2,_1,N,...) \
FOREACHTAIL_##N
#define FOREACHTAIL(f,...) \
FOREACHTAIL_N(__VA_ARGS__,4,3,2,1)(f,__VA_ARGS__)
// if there are two arguments, expand to true. Otherwise false.
#define IFTWO_N(_0,_1,N,...) N
#define IFTWO(true, false, ...) IFTWO_N(__VA_ARGS__, true, false)
// If empty, expand to true, otherwise false.
// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
#define IFEMPTY(true, false, ...) IFTWO(true, false, COMMA __VA_ARGS__ ())
// Join arguments with `_`.
#define JOIN_U(a, b) a##_##b
#define JOIN_TWO_IN(a,b) IFEMPTY(FIRST, JOIN_U, b)(a, b)
#define JOIN_TWO(a,b) JOIN_TWO_IN(a,b)
#define JOIN(...) FOREACHTAIL(JOIN_TWO, __VA_ARGS__)
// Append WORD_ to each argument and join arguments with spaces.
#define WORD_ /* the last one expands to empty */
#define WORDS_TWO(a, b) WORD_##a b
#define WORDS(...) FOREACHTAIL(WORDS_TWO, __VA_ARGS__)
#define REPLACE_SPACES_TO_UNDERSCORES(a) JOIN(WORDS(WORDS(WORDS(WORDS(WORDS(a))))))
// --------------------------------------------
#define ID_double 1
#define ID_float 2
#define ID_long_double 3
#define ID_IN2(x) ID_##x
#define ID_IN(x) ID_IN2(x)
#define ID(x) ID_IN(REPLACE_SPACES_TO_UNDERSCORES(x))
int main() {
#define T long double
T v;
int x = ID(T); /* 3 */
}

Expand the concatenated text to be a macro and then expand the Macro again

#include <stdio.h>
#define X 2
#define N_1_T 50
#define N_2_T 49
#define PRINT() printf("id: %d", N_ ## X ## _T)
int main(void)
{
PRINT();
return 0;
}
I want N_ ## X ## _T to be expanded to N_2_T when I have the Macro #define X 2. If I change the Macro definition of X to be #define X 1, N_ ## X ## _T should be expanded to N_1_T.
But I do not know how to do this. I have searched and read many pages, but I just do not get what I should do to achieve the desired result.
Please help, thank you.
To achieve what you want, the X macro must be expanded to the pre-processor token 2 before concatenation, so the macro containing the ## must get passed an expanded 2. It is very similar to this: Stringification - how does it work?
You can solve this with a number of helper macros that enforce rescanning of the pp tokens:
#include <stdio.h>
#define X 2
#define N_1_T 50
#define N_2_T 49
#define CONCAT(n) N_ ## n ## _T
#define GET_ID(n) CONCAT(n)
#define PRINT() printf("id: %d", GET_ID(X))
int main(void)
{
PRINT();
return 0;
}
Output:
id: 49

Error in C preprocessor concatenation with variable and function (dynamically indexing in a for loop)

I ran this code in this compiler
#define CCc(n) CC_##n
#define CC(n) CCc(n)
#define CC_1 (1,2)
#define CC_2 (3,4)
#define CALL_FUNCTION(xy) Coord(xy)
#define YES 1
#define NO 0
int Coord(x, y){
if (x < 0.5 && y < 1.5){
return YES;
}
return NO;
}
int main()
{
for(int i = 1; i < 3; i++){
CALL_FUNCTION(CC(i));
}
return 0;
}
and got this error:
error: use of undeclared identifier 'CC_i'
Why does this error occur? And what is the right way to achieve this?
You cannot do run-time/variable evaluations in the pre-processor. It requires compile-time pre-processor tokens. So rather than trying to define a number of #define based on run-time values, you should gather all compile-time constants in one place.
A common way to do so is "X macros". In your case it might look like this:
#define CC_LIST \
/* n x y */ \
X(1, 1, 2) \
X(2, 3, 4) \
int main()
{
#define X(n,x,y) (void) Coord(x, y);
CC_LIST
#undef X
return 0;
}
This expands to (void) Coord(1,2); (void) Coord(3,4);, so it is a compile-time loop unrolling of sorts.
Alternatively, if you insist on having the "CC_N" macros because they are also needed for other purposes, you can do this:
#define CC_LIST \
/* n */ \
X(1) \
X(2) \
#define CC(n) CC_##n
#define CC_1 1,2
#define CC_2 3,4
#define CALL_FUNCTION(...) (void) Coord(__VA_ARGS__);
int main()
{
#define X(n) CALL_FUNCTION(CC(n))
CC_LIST
#undef X
return 0;
}
As you can tell, macro tricks like "X macros" are not easy to read and should be regarded as the last resort. Only use them when proper program re-design is not possible, for example during maintenance of existing code.

Adding separators in iteration over __VA_ARGS__ in C/C++ macro

background
I'm trying to make automatic generator of Lua-C interface using C macros. The biggest problem was to make it general for varying number of arguments, which I resolved by using __VA_ARGS__ with help of this answer: Is it possible to iterate over arguments in variadic macros?
Simpler almost working solution
this solution almost works, but it produce some redudant commas (nottice ,,,, in output)
// helper macros for iteration over __VA_ARGS__
#define ARG1(WHAT,X,...) WHAT(X)ARG2(WHAT,__VA_ARGS__)
#define ARG2(WHAT,X,...) WHAT(X)ARG3(WHAT,__VA_ARGS__)
#define ARG3(WHAT,X,...) WHAT(X)ARG4(WHAT,__VA_ARGS__)
#define ARG4(WHAT,X,...) WHAT(X)ARG5(WHAT,__VA_ARGS__)
#define ARG5(WHAT,X,...) WHAT(X)ARG6(WHAT,__VA_ARGS__)
#define ARG6(WHAT,X,...) WHAT(X)//ARG2(__VA_ARGS__)
// macros dispatch propper type of Lua::get
#define LUA_GET_int(i) Lua::getInt(L,i)
#define LUA_GET_long(i) Lua::getInt(L,i)
#define LUA_GET_float(i) (float)Lua::getDouble(L,i)
#define LUA_GET_double(i) Lua::getDouble(L,i)
#define LUA_GET_string(i) Lua::getString(L,i)
#define LUA_PUSH_int(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushnumber(L,a)
#define LUA_PUSH_double(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushstring(L,a)
#define LUA_GET_(T)
#define LUA_GET(T) ,LUA_GET_##T(i++) // commas come from here
#define MAKE_LUA_FUNC(TR,fname,T1,...) int l_##fname(lua_State * L){ int i=0; LUA_PUSH_##TR( fname( LUA_GET_##T1(i++) ARG1(LUA_GET,__VA_ARGS__) ) ); return 1; }
// interface for function:
// double add3(float, int, double );
MAKE_LUA_FUNC( double, add3, float, int, double )
// output:
// 'int l_add3(lua_State * L){ int i=0; lua_pushnumber(L,add3((float)Lua::getDouble(L,i++) ,Lua::getInt(L,i++),Lua::getDouble(L,i++),,,, )); return 1; }'
Working but less-nice solution
I had to duplicate LUA_GET_ macros for case when it is first in argument list (without comma) and otherwise (with comma in front)
// begin of argument list => no commas
#define LUA_GET_int(i) Lua::getInt(L,i)
#define LUA_GET_long(i) Lua::getInt(L,i)
#define LUA_GET_float(i) (float)Lua::getDouble(L,i)
#define LUA_GET_double(i) Lua::getDouble(L,i)
#define LUA_GET_string(i) Lua::getString(L,i)
// rest of argument list => with commas
#define LUA_GET__int(i) ,Lua::getInt(L,i)
#define LUA_GET__long(i) ,Lua::getInt(L,i)
#define LUA_GET__float(i) ,(float)Lua::getDouble(L,i)
#define LUA_GET__double(i) ,Lua::getDouble(L,i)
#define LUA_GET__string(i) ,Lua::getString(L,i)
#define LUA_PUSH_int(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushnumber(L,a)
#define LUA_PUSH_double(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushstring(L,a)
#define LUA_GET_(T)
#define LUA_GET__(T)
#define LUA_GET(T) LUA_GET__##T(i++)
#define MAKE_LUA_FUNC(TR,fname,T1,...) int l_##fname(lua_State * L){ int i=0; LUA_PUSH_##TR( fname( LUA_GET_##T1(i++) ARG1(LUA_GET,__VA_ARGS__) ) ); return 1; }
// MAKE_LUA_FUNC( double, add3, float, int, double )
// output:
// int l_add3(lua_State * L){ int i=0; lua_pushnumber(L,add3( (float)Lua::getDouble(L,i++) ,Lua::getInt(L,i++),Lua::getDouble(L,i++) )); return 1; }
Is it possible to make it simpler / nicer ?
NOTE - for debugging I found very useful this Seeing expanded C macros in particular https://stackoverflow.com/a/31460434/1291544
You need to count the number of arguments you have, and then call the corresponding ARG# macro.
#define ARGS_N(M,...) \
ARGS_N__(__VA_ARGS__, 6, 5, 4, 3, 2, 1)(M, __VA_ARGS__)
#define ARGS_N__(_1, _2, _3, _4, _5, _6, X, ...) ARGS_##X
#define ARGS_1(M, X) M(X)
#define ARGS_2(M, X, ...) M(X)ARGS_1(M, __VA_ARGS__)
#define ARGS_3(M, X, ...) M(X)ARGS_2(M, __VA_ARGS__)
#define ARGS_4(M, X, ...) M(X)ARGS_3(M, __VA_ARGS__)
#define ARGS_5(M, X, ...) M(X)ARGS_4(M, __VA_ARGS__)
#define ARGS_6(M, X, ...) M(X)ARGS_5(M, __VA_ARGS__)
Now, change MAKE_LUA_FUNC to call ARGS_N instead of your ARG1.
The way the counting technique works is that ARGS_N invokes the helper ARGS_N__ with the variable arguments, and then pads out the invocation with additional arguments. ARGS_N__ does the counting by always utilizing the 7th argument. So, if ARGS_N is provided 4 variable arguments after the first one, ARGS_N__ will produce ARGS_4, because in that case, in the padding provided by ARGS_N, 4 would be the 7th argument.
ARGS_N__(__VA_ARGS__, 6, 5, 4, 3, 2, 1)(M, __VA_ARGS__)
. .
/|\ /|\
| |
If this has 4 arguments
|
This would be the 7th argument
This is the same technique that was shown in the answer you pointed to. However, that version was a bit more complicated than the version I am illustrating for you, so hopefully you will find this explanation helpful.

Use multiple macros in a macro definition

I'm trying to use multiple macros in the definition of another macro, but seem to have problems concatenating them together. Here's a very simplified version of what I'm trying to do:
#include <stdio.h>
#define PICK_SET_A
#ifdef PICK_SET_A
#define SET A
#endif
#ifdef PICK_SET_B
#define SET B
#endif
#define ENABLE_VAR_1_A 1
#define ENABLE_VAR_2_A 1
#define ENABLE_VAR_1_B 0
#define ENABLE_VAR_2_B 0
#define MACRO_RESOLVE(var,set) ENABLE_VAR_##var##_##set
#define ENABLE_VAR_1 MACRO_RESOLVE(1, SET)
#define ENABLE_VAR_2 MACRO_RESOLVE(2, SET)
int main(int argc, char **argv) {
fprintf(stdout, "VALUE: %d\n", ENABLE_VAR_1);
return 0;
}
I would expect the result to be 0.
However, I'm getting compile errors because the MACRO_RESOLVE macro isn't resolving the way I expect it to:
$ gcc -o asdf asdf.c
asdf.c:25:36: error: use of undeclared identifier 'ENABLE_VAR_1_SET'
fprintf(stdout, "VALUE: %d\n", ENABLE_VAR_1);
^
asdf.c:20:26: note: expanded from macro 'ENABLE_VAR_1'
#define ENABLE_VAR_1 MACRO_RESOLVE(1, SET)
^
asdf.c:18:32: note: expanded from macro 'MACRO_RESOLVE'
#define MACRO_RESOLVE(var,set) ENABLE_VAR_##var##_##set
^
<scratch space>:229:1: note: expanded from here
ENABLE_VAR_1_SET
^
1 error generated.
So it looks like SET isn't getting expanded when I define ENABLE_VAR_1.
Since you are trying to build a macro name, you need to do enough intermediate expansions along the way for all tokens to expand. See it live here.
#include <stdio.h>
#define PICK_SET_A
#ifdef PICK_SET_A
#define SET A
#endif
#ifdef PICK_SET_B
#define SET B
#endif
#define ENABLE_VAR_1_A 1
#define ENABLE_VAR_2_A 1
#define ENABLE_VAR_1_B 0
#define ENABLE_VAR_2_B 0
#define MACRO_RESOLVE__(M) M
#define MACRO_RESOLVE_(V, S) MACRO_RESOLVE__(ENABLE_VAR_ ## V ##_## S)
#define MACRO_RESOLVE(var,set) MACRO_RESOLVE_(var, set)
#define ENABLE_VAR_1 MACRO_RESOLVE(1, SET)
#define ENABLE_VAR_2 MACRO_RESOLVE(2, SET)
int main(int argc, char **argv) {
fprintf(stdout, "VALUE: %d\n", ENABLE_VAR_1);
return 0;
}

Resources