What does slash mean in macro definitions of C language? [duplicate] - c

This question already has answers here:
What does ## in a #define mean?
(6 answers)
Closed 6 years ago.
I am new to C programming and I have difficulty to understand what following code does? What does '##' in macro mean, also I don't quite understand how in macro definitions we have for example f1, but without arguments.
My question is different because I also have multiple defines
#include <stdio.h>
int a=1, b=2;
#define M(a,b) a ## b(a)
#define a t(f1,t(f1,f2(b)))
#define b(x) t(f2,t(f2,f1(a)))
#define ab(x) a+b(b)
typedef int (*i2i)(int);
int f1(int x) { return (++x); }
int f2(int x) { return (--x); }
int t(i2i f,int x) {return(f(f(x)));}
int main()
{
printf("%d\n%d", M(a,b), ab(5));
return (0);
}

The double-octothorpe "##" is known as the token-pasting operator. Whatever is on either side of it will be concatenated to form a single string. It lets you combine an argument with a fixed string, or combine two arguments. For example:
#define ADD_UNDERLINE(x) _ ## x ## _
ADD_UNDERLINE(foo) // generates: _foo_
In your case, you have:
#define M(a,b) a ## b(a)
M(foo,bar) // generates: foobar(foo)
Regarding your question about f1:
The macros use bare function names, but they're used as parameters to the function t. The first parameter of t is type i2i, which is defined (via typedef) as a pointer to a function. Using just the bare function name here is generally equivalent to a pointer to that function (note: this isn't standard and would be better written in the macro as "&f1").

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.

Can anyone explain the concatenation on #define like that: [duplicate]

#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;
The above line is take from Unreal 4, and I know I could ask it over on the unreal forums, but I think this is a general C++ question that warrants being asked here.
I understand the first line defines a macro, however I am not well versed in preprocessor shenanigans in C++ and so I'm lost over there. Logic tells me the backslash means the declaration continues onto the next line.
FThreadSafeStaticStat looks a bit like a template, but there's #'s going on in there and a syntax I've never seen before in C++
Could someone tell me what this means? I understand that you may not have access to Unreal 4, but it's just the syntax I don't understand.
## is the preprocessor operator for concatenation.
So if you use
DEFINE_STAT(foo)
anywhere in the code, it gets replaced with
struct FThreadSafeStaticStat<FStat_foo> StatPtr_foo;
before your code is compiled.
Here is another example from a blog post of mine to explain this further.
#include <stdio.h>
#define decode(s,t,u,m,p,e,d) m ## s ## u ## t
#define begin decode(a,n,i,m,a,t,e)
int begin()
{
printf("Stumped?\n");
}
This program would compile and execute successfully, and produce the following output:
Stumped?
When the preprocessor is invoked on this code,
begin is replaced with decode(a,n,i,m,a,t,e)
decode(a,n,i,m,a,t,e) is replaced with m ## a ## i ## n
m ## a ## i ## n is replaced with main
Thus effectively, begin() is replaced with main().
TLDR; ## is for concatenation and # is for stringification (from cppreference).
The ## concatenates successive identifiers and it is useful when you want to pass a function as a parameter. Here is an example where foo accepts a function argument as its 1st argument and the operators a and b as the 2nd and 3rd arguments:
#include <stdio.h>
enum {my_sum=1, my_minus=2};
#define foo(which, a, b) which##x(a, b)
#define my_sumx(a, b) (a+b)
#define my_minusx(a, b) (a-b)
int main(int argc, char **argv) {
int a = 2;
int b = 3;
printf("%d+%d=%d\n", a, b, foo(my_sum, a, b)); // 2+3=5
printf("%d-%d=%d\n", a, b, foo(my_minus, a, b)); // 2-3=-1
return 0;
}
The # concatenates the parameter and encloses the output in quotes. The example is:
#include <stdio.h>
#define bar(...) puts(#__VA_ARGS__)
int main(int argc, char **argv) {
bar(1, "x", int); // 1, "x", int
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__}

(C) macro that contains 2 args in macro doesn't compile, but it works well in function. I want to know why. Thanks

Yesterday I tried to optimize my code using macro, but it doesn't compile in some sentences. For simplification, I writed codes below to describe what I want to work out:
#define MACRO(x, y) ((x) + (y))
#define X 2,3
int fun(x, y)
{
return x+y;
}
int main(void)
{
int res;
res = fun(X); //ok
res = MACRO(X); //**error:macro "MACRO" requires 2 arguments, but only 1 given**
printf("%d\n", res);
return 0;
}
I used to believe that macros simply replace words so it's no problem to do this, but now I think I was wrong. :(
More accurately: I was tring to do something like:
//global.h
#define MACRO(brief, num) fun(__LINE__, brief, num)
//test.c
#include <global.h>
#define X "brief",3
void fun(int line_num, char* brief, int num)
{
printf("%d, %s,%d\n", line_num, brief, num); //do something
}
int main(void)
{
fun(__LINE__, X); //ok
MACRO("brief",3); //ok
MACRO(X); //error: macro "MACRO" requires 2 arguments, but only 1 given
return 0;
}
So I need to use this type of macro to reduce args.
I searched everywhere yesterday but nothing was found, I hope I could receive answers here. Thanks a lot. :)
(My English is not very good, I wish I had a clear description of my problem.)
You can use the variable arguments facility of the preprocessor, as in the following example (available on IdeOne):
#include <stdio.h>
#define MACRO(...) MACRO_IMPLEMENTATION(__VA_ARGS__)
#define MACRO_IMPLEMENTATION(x,y) ((x)+(y))
#define X 2,3
int main (void) {
printf ("MACRO (X) = %d\n", MACRO (X));
printf ("MACRO (2,3) = %d\n", MACRO (2,3));
return 0;
}
The output is
MACRO (X) = 5
MACRO (2,3) = 5
The definition of MACRO takes a variable number or arguments, which are bound to __VA_ARGS__ (see section 6.10.3 in the standard). The definition of MACRO calls MACRO_IMPLEMENTATION which now sees two arguments either because MACRO was called with two or because it was called with an argument which expands to a list of two arguments.

Using ## operator [duplicate]

This question already has answers here:
What are the applications of the ## preprocessor operator and gotchas to consider?
(13 answers)
Closed 6 years ago.
I am having a code that says:
#include<stdio.h>
typedef struct string{
char *ch_ptr;
}str_t;
#define newdef(a,b) \
char a ## sumthing[b * sizeof(str_t)]; \
str_t *a = (str_t *)a ## sumthing
main(){
newdef(input,5);
/* some lines of code */
}
Optional changes to code:
#include<stdio.h>
typedef struct string{
char *ch_ptr;
}str_t;
#define newdef(a,b) \
char a ## sumthing[b * sizeof(str_t)]; \
str_t *var1 = (str_t *)a ## sumthing
main(){
newdef(input,5)="Hello";
printf("%s\n",input);
/* some lines of code */
}
Can anyone explain what this code segment means? Is input in this code a string (hope not) or a variable? If a variable then why doesn't the compiler throw an undeclared variable error?
Its a preprocessor concatenation operator, and can only be used when defining preprocessor macros.
Lets take a simple example
#define CONCAT(a, b) a ## b
int CONCAT(foo, bar);
In the above code, the invocation of CONCAT(foo, bar) will be replaced by
int foobar;
input is neither a string nor a variable, it's a preprocessing token.
## is the "token-pasting" operator.
The first macro expands newdef(input,5); into
char inputsumthing[5 * sizeof(str_t)]; str_t *input = (str_t *) intputsumthing;
That is, it expands into a declaration of a variable named like the first parameter.
Your "optional changes" would unconditionally name the declared pointer variable "var1" and make it impossible to use the macro more than once in the same scope.
Also, newdef(input,5)="Hello"; would expand to an error:
char inputsumthing[5 * sizeof(str_t)];
str_t *var1 = (str_t *)inputsumthing = "Hello";
As a side note, the original macro seems to mostly be an obfuscation of
str_t inputs[5];
str_t* input = inputs;

Resources