C Preprocessor variable concatenation with "." - c

I'm aware of multiple Q&As [1, 2]that touch closely on this subject, and I've tried to implement their solutions but the fact that I need to use the . in my concatenation seems to be causing me trouble.
This is what I want:
#include <stdio.h>
#define PROPERTY .value1
#define MAKE_PROP(var) var##PROPERTY
typedef struct {
int value1;
int value2;
} Node;
int main(void) {
Node node;
node.value1 = 1;
node.value2 = 2;
// MAKE_PROP(node) should evaluate to "node.value1".
printf("%d", MAKE_PROP(node));
return 0;
}
However it's giving me all sorts of errors. If I try the PASTER-EVALUATE idea from [2] then it tells me "pasting "." and "PROPERTY" does not give a valid preprocessing token".
Anyone know how to accomplish what I need? It's essential that it stays general and that I can use the var as this is something I'd like to call multiple times on different variable names.

It's not working for two reasons:
The token concatenation operator suppresses the expansion of macros that are used as its operands. So you get nodePROPERTY. The solution to that is to add a level of indirection:
#define PROPERTY .value1
#define CONCAT(a, b) a##b
#define MAKE_PROP(var) CONCAT(var, PROPERTY)
Now PROPERTY is expanded before being fed as an argument to CONCAT.
The result of concatenating tokens must be a single valid token, but node.value1 is 3 tokens (node, . and value1).
Now, it just so happens that you don't need concatenation at all, you just need to build the expression (node .value1) which can be done with following simple macros1:
#define PROPERTY value1
#define MAKE_PROP(var) ( (var).PROPERTY )
1: simplified with the help of Lundin.

Related

How to create a function-like macro token by pasting tokens together

I have a set of predefined macros (That I cannot change) where each one takes as input the index for an array. I want to create another macro to be able to choose which previously defined macro to use by pasting the tokens together.
I have tried creating a macro that takes in 2 arguments: x, which picks which previously defined macro to use, and ind, which is passed on to the selected macro.
The code below is ran using
https://www.onlinegdb.com/online_c_compiler
so I can figure out the basic code before I put it into a rather large application.
#include <stdio.h>
//struct creation
struct mystruct {
int x;
int y;
};
//create array of structs
struct mystruct sArr1[2] = {{1,2},{3,4}};
struct mystruct sArr2[2] = {{5,6},{7,8}};
//define macros
#define MAC1(ind) (sArr1[ind].x)
#define MAC2(ind) (sArr2[ind].y)
// Cannot change anything above this //
//my attempt at 2 input macro
#define MYARR(x,ind) MAC ## x ## (ind)
int main() {
printf("%d\n", MYARR(1, 0));
return 0;
}
I want the result to print out the x value of sArr1 at index 0, which is 1. Instead, I get this output
main.c: In function ‘main’:
main.c:29:22: error: pasting "MAC1" and "(" does not give a valid preprocessing token
#define MYARR(x,ind) MAC ## x ## (ind)
^
main.c:33:19: note: in expansion of macro ‘MYARR’
printf("%d\n", MYARR(1, 0));
line 29 should be :
#define MYARR(x,ind) MAC##x(ind)
I tested it. It printed '1', which is what you want.

Prepocessor ## Operator and variable

Is there a way to "generate" a function name by using the operator ## and a variable value. For example:
#define FUN_I(fun, fun_id) fun##fun_id
#define FUN(fun, fun_id) RECV_CB_FUN_I(fun, fun_id)
int foo0(int x) {
// do something
}
int main()
{
int i = 0;
FUN(foo,i)(1);
}
Macro FUN generates fooi. Is there a way to get foo0 somehow, or I have to use the actual number 0 in this case, e.g FUN(foo, 0)(1);
Cheers
You have to use actual 0 (or another macro). Macro expansion is handled by the C pre-processor at compile time. It knows nothing about runtime values of variables.
As stated, the macro expansion is done at compile time, so the function name wouldn't be know at run time.
It is more appropriate to use function pointers and an array to them.
Example:
typedef int (*TFoo)(int);
int foo1(int x)
{
printf("from foo1: x = %d\n", x);
return 0;
}
int foo2(int x)
{
printf("from foo2: x = %d\n", x);
return 0;
}
TFoo foos[2] = {foo1, foo2};
#define foo(i, x) foos[i](x)
That's that. Hope it helps
'c' preprocessing is a process of replacing macros with the text from their definitions. some operations like ## allow to add its argument as text into definitions. So, everything is done even before compilation starts.
As a result, in your case FUN(fun,i) will be substituted as text and form funi. The only limited way to build function names like you want is to use actual text values or other macros. Here are 2 examples which will work with pre-processing:
FUN(fun, 0)(1);
or
#define I 0
FUN(fun, I)(1);
In the last case I is a macro itself, therefore it also works. (it is always a good idea to name macro name in upper case letters).

Concatenate strings in #define without strcat

In the project that I'm working on I have a code similar to this one:
#include<stdio.h>
struct parameter_struct{
char *parameter_name;
int parameter_value;
};
int main(){
struct parameter_struct param1= {"x_custom_param1", 6};
printf("parameter name: %s\n", param1.parameter_name);
return 0;
}
what I need to achieve now is to make the parameter name dynamic using predefined macro:
#define macro_custom "x_custom1_"
so the parameter name should be the macro value concatenated with "param1" substring. I mean it will be "x_custom1_param1" instead of the actual static value "x_custom_param1".
In my project all parameters are statically declared like that:
{"x_custom_param1", 6};
and I mustn't touch this structure of code. So I can't initialize those parameters dynamically in c function for example and use strcat in this function.
So what I thought about is to use an other #define with ## statement. So my code will be like that:
#include<stdio.h>
#define macro_custom "x_custom1_"
#define f(g,h) g##h
struct parameter_struct{
char *parameter_name;
int parameter_value;
};
int main(){
struct parameter_struct param1= {f(macro_custom, "param1"), 6};
printf("parameter name : %s\n", param1.parameter_name);
return 0;
}
but I get a compilation error:
error: pasting "macro_custom" and ""param1"" does not give a valid preprocessing token
struct parameter_struct param1= {f(macro_custom, "param1"), 6};
and that seems logical because the macro that I defined doesn't return a string with ##
Has someone an idea how I can correct my idea? or is there a better idea?
The feature you are looking for is string pasting. Adjacent string constants will be combined by the compiler -- you don't need an operator.
#define f(g, h) (g h)
Keep in mind that this trick only works for string constants. It won't work on variables.
it's simpler then what I thought. I found it in an old project.
#include<stdio.h>
#define macro_custom "x_custom1_"
struct parameter_struct{
char *parameter_name;
int parameter_value;
};
int main(){
struct parameter_struct param1= {macro_custom"param1", 6};
printf("parameter name : %s\n", param1.parameter_name);
return 0;
}
String literals can be concatenated this way "str1""str2"
macro function can concatenate two string literals - #define STRCAT(str1, str2) str1##str2
And when it comes to variables, you use strcat()
More efficient approach is to use string managing utilities such as GString.
It keeps track of the end of string and it handles memory expansions for you.
Keeping track of the end of string is always cost-free operation, as you always reach the end when copying it anyway.
Another approach is to use strchr() to find \0 and then copy string with conventional methods at this offset plus one byte forwards.
Also, I think OP's question would be much clearer if it states that string concatenation at compile / pre-processor (the comment belows throws some light on the exact phase it happens in) time is needed.
Those concepts uncover entire different universes.
Try the ‘#’ preprocessing operator which convert a macro argument into a string constant.
#define NEW_PARA_STRUCT(paramx, value) struct parameter_struct paramx={(macro_custom #paramx), value}
Example:
#include <stdio.h>
#define macro_custom "x_custom1_"
#define f(g,h) (g h)
#define NEW_PARA_STRUCT(paramx, value) struct parameter_struct paramx={(macro_custom #paramx), value}
struct parameter_struct{
char *parameter_name;
int parameter_value;
};
int main(){
struct parameter_struct param1= {f(macro_custom, "param1"), 6};
NEW_PARA_STRUCT(param2, 7);
printf("parameter name : %s\n", param1.parameter_name);
printf("parameter name : %s\n", param2.parameter_name);
return 0;
}

C preprocessor init array

I'm writing a complex macro and I need to pass also array initializer. Basically I have trouble to do:
#define INIT_ARR(VAR_NAME,ARR_DATA) int VAR_NAME[] = ARR_DATA
then I would call it
INIT_ARR(myNm,{1,2,3});
but preprocessors interprets any commas (also the one inside curly braces) as new macro parameter so it gives me error:
error: #55-D: too many arguments in invocation of macro "INIT_ARR"
preprocessor does not ignore () so I can do:
#define INIT_ARR(VAR_NAME,ARR_DATA) int VAR_NAME[] = {ARR_DATA}
INIT_ARR(myNm,(1,2,3));
but then it is interpreted as
int myNm[] = {(1,2,3)};
which is not correct for C.
Is there a way how to do it?? For example remove braces from parameter?
I think I cracked it:
#define myArgs(...) __VA_ARGS__
#define INIT_ARR(VAR_NAME,ARR_DATA) int VAR_NAME[] = {myArgs ARR_DATA}
INIT_ARR(myArr,(1,2,3,4));
will be interpreted correctly as:
int myArr[] = {1,2,3,4};
annoying_squid's answer helped me to figure it out...
You can use variable number of arguments with the macro as -
#define INIT_ARR(VAR_NAME, ...) int VAR_NAME[] = {__VA_ARGS__}

Counting preprocessor macros

I have this macro code, which allows me to define both a C enum and a list of the enumerated names as strings using one construct. It prevents me from having to duplicate enumerator names (and possibly introducing errors for large lists).
#define ENUM_DEFINITIONS(F) \
F(0, Item1) \
F(5, Item2) \
F(15, Item3) \
...
F(63, ItemN)
then:
enum Items {
#define ITEM_ENUM_DEFINE(id, name) name = id,
ENUM_DEFINITIONS(ITEM_ENUM_DEFINE)
#undef ITEM_ENUM_DEFINE
which, when expanded, should produce:
enum Items {
Item1 = 0,
Item2 = 5,
Item3 = 15,
...
ItemN = 63,
}
In the implementation file, I have this code:
const char* itemNames[TOTAL_ITEMS];
int iter = 0;
#define ITEM_STRING_DEFINE(id, name) itemNames[iter++] = #name;
ENUM_DEFINITIONS(ITEM_STRING_DEFINE)
#undef ITEM_STRING_DEFINE
which, when expanded, produces:
itemNames[iter++] = "Item1";
itemNames[iter++] = "Item2";
itemNames[iter++] = "Item3";
...
itemNames[iter++] = "ItemN";
I'd like to know how many enumerator items I've created in this fashion and be able to pass it to compile-time arrays. In the example above, this would be determining that TOTAL_ITEMS = N at compile-time. Is it possible to count macro invocations in this way?
I've seen mention of a non-standard COUNTER macro, similar to the FILE and LINE macros, but I'm hoping there is a more standard way.
Would also be interested in hearing if there is a better way to achieve this without having to use macros.
The following should work:
#define ITEM_STRING_DEFINE(id, name) #name, // note trailing comma
const char *itemNames[] = {
ENUM_DEFINITIONS(ITEM_STRING_DEFINE)
};
#define TOTAL_ITEMS (sizeof itemNames / sizeof itemNames[0])
Edit: Thank you to Raymond Chen for noting we don't have to worry about the unnecessary final comma in the list. (I had been misremenbering the problem for enums with strict C89 compilers, as in Is the last comma in C enum required?.)
You can use the same technique to count the invocations.
enum itemscounter {
#define ITEM_ENUM_DEFINE(id, name) name##counter,
ENUM_DEFINITIONS(ITEM_ENUM_DEFINE)
#undef ITEM_ENUM_DEFINE
TOTAL_ITEMS
};
Would also be interested in hearing if there is a better way to achieve this without having to use macros.
You could always use a scripting language such as ruby or python to generate .c and .h files for you. If you do it well, you can integrate your script into your Makefile.
I know this isn't a complete answer.
You can create a macro around something like this.
#include <stdio.h>
const char * array[] = {
"arr1", "arr2", "arr3", "arr4"
};
int main (int argc, char **argv)$
{
printf("%d\n", sizeof(array)/sizeof(const char *));
}
If you can modify your enum so it has continous elements you can do sth like this (from Boost)
enum { A=0,B,C,D,E,F,N };
const char arr[N]; // can contain a character for each enum value
See the suggestions Mu Dynamics 'Enums, Strings and Laziness'; these are at least related to what you're after.
Otherwise, look at the Boost Preprocessor collection (which is usable with the C preprocessor as well as the C++ preprocessor).

Resources