What is wrong? I would like the xconcat line to work.
#define concat(a,b) a ## b
#define xconcat(a,b) concat(a,b)
int main() {
xconcat(xconcat(boost::variant<,int), >) y;
boost::variant<int> x;
return 0;
}
g++ -E x.cpp
# 1 "x.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x.cpp"
int main() {
x.cpp:5:1: error: pasting "<" and "int" does not give a valid preprocessing token
x.cpp:5:1: error: pasting "int" and ">" does not give a valid preprocessing token
boost::variant<int > y;
boost::variant<int> x;
return 0;
}
The token pasting operator technically can't be used to paste something that doesn't end up being a token. GCC enforces that restriction, while some other compilers don't (the ## operator just seems to perform basic concatenation of the strings which then gets tokenized later).
From C++11 16.3.3/3 "The ## operator":
If the result is not a valid preprocessing token, the behavior is undefined.
The same language is in pretty much every C and C++ standard going back to C90.
In your case you don't need to use token pasting since you're dealing with separate tokens anyway:
#define yyconcat(a,b) a b
#define yconcat(a,b) yyconcat(a,b)
int main() {
yconcat(yconcat(boost::variant<,int), >) y;
boost::variant<int> x;
return 0;
}
g++ -E so-test.c
C:\so-test>g++ -E so-test.c
# 1 "so-test.c"
# 1 "<command-line>"
# 1 "so-test.c"
int main() {
boost::variant< int > y;
boost::variant<int> x;
return 0;
}
Related
I tried to implement template like functionality in C by use of macros, but for some reason it throws me the error "c:4:25: error: expected identifier or '(' before '{' token"
Here's the code
#include<stdio.h>
#include<stdlib.h>
#define test(name, type){\
typedef struct{\
type x;\
type y;\
}name;\
}
test(IntVec2, int);
int main(){
printf("Hello, World!");
}
One way to debug this type of situation is to take a look at the output of the preprocessor. For exampl, we feed the following through the cpp preprocessor:
#define test(name, type){\
typedef struct{\
type x;\
type y;\
}name;\
}
test(IntVec2, int);
(I have omitted some of the code)
The result of the cpp program, is something like:
# 0 "test.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "test.c"
{ typedef struct{ int x; int y; }IntVec2;};
Now it becomes immediately apparent that the first { and last } should not have been in the macro definition.
Thus:
#define test(name, type)\
typedef struct{\
type x;\
type y;\
}name;
test(IntVec2, int);
Now leads to:
# 0 "test.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "test.c"
typedef struct{ int x; int y; }IntVec2;;
Note that even now, the ; at the end is obsolete (but relatively harmless in this specific case. Be very careful when using ; within macro definitions.
Removing the brackets solves the problem as {typedef...} is not a valid declaration as stated by Mat in the comments.
6.10.3.3 of the c11 spec says
each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token. [...] If the result is not a valid preprocessing token, the behavior is undefined.
So 1 ## ## would be replaced with 1##, which is not a valid preprocessing token, so the behaviour is undefined.
Is that correct?
#include <stdio.h>
int main()
{
#define foo 1 ## ## 2
printf("%d\n", foo);
return 0;
}
Compiling the above with gcc -std=c11 -Wall -Wpedantic doesn't give any warnings, and the output is 12 as if there were only one ##. Is that the expected output?
gcc (GCC) 4.7.2
c89
Is it possible to stringify a variadic macro?
I have the following macro and I want to output the resulting string from the fmt and arguments.
#define ERROR_MESSAGE(priority, fmt, ...) \
do { \
MODULE_LOG(priority, fmt, ##__VA_ARGS__);\
} while(0)
So, I just want to get the complete string of the fmt and the ##__VA_ARGS__ so I can assign it to a char * to perform some additional operations on it.
Um, no. Preprocessing happens before the code is even compiled. It exists in a completely different universe from the executing program. One thing you can do, is run just the pre-processing step and examine the output (use the gcc switch -E to print the preprocessor output).
About the most you can do is to redirect this to a file, and then read the file in the program.
On further thought, let me back-off from "no", and change it to "maybe". Take a look at this other answer of mine, that implements a "foreach" macro for variadic macros.
So, using APPLYXn (and, implicitly, PPNARG), you could apply a STR(x) #x macro to the args like this (n.b. as written, APPLYXn can handle up to 15 arguments):
#define X(x) #x
#define ERROR_MESSAGE(priority, fmt, ...) \
"do {MODULE_LOG(" X(priority) X(fmt) APPLYXn(__VA_ARGS__) ");} while(0)"
int main() {
printf("%s\n", ERROR_MESSAGE(3, "%d", 5) );
return 0;
}
gcc -E produces
# 1 "strvar.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "strvar.c"
# 71 "strvar.c"
int main() {
printf("%s\n", "do {MODULE_LOG(" "3" "\"%d\"" "5" ");} while(0)" );
return 0;
}
And the compiler will concatenate all these string literals into one string.
#define B 100+B
main()
{
int i= B;
}
I know it's wrong, but just out of curiosity, when I compile it I get this weird error:
"B was not declared in this scope".
Why is it so? If this error was because the compiler removes the macro after its substitution then how does the following code worked fine, when B must have been removed before it was made available to A ?
#define B 100
#define A 100+B
main()
{
int i= B;
int j =A;
}
Here's the output of the preprocessor:
gcc -E x.c
# 1 "x.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x.c"
main()
{
int i= 100+B;
}
As you can see, it did the substituion. Now comes the compile step which fails because there's no B declared.
The other code is fine, here's the output:
main()
{
int i= 100;
int j =100+100;
}
Macro expansion isn't done recursively, if the macro name appears in the replacement text, it isn't expanded again. So with
#define B 100 + B
a replacement of B yields the token sequence 100 + B and B is not expanded again (if it were, you'd have an infinite recursion). So the compiler sees a reference to the undeclared variable B after the preprocessor finished.
But in
#define B 100
#define A 100 + B
when the macro A is expanded, the macro name B appears in the replacement text. Then B is expanded and the compiler sees 100 + 100 which contains no references to undeclared variables.
macro replacement are simple text operation.you can debug this type of problem in a simple step by step compile.
use cc -E filename.c -O filename.i
for generate extended c code
vi filename.i for reading pure/extended c code
#define f(g,g2) g##g2
main()
{
int var12=100;
printf("%d",f(var,12));
}
The above program prints 100 in c by concatenating var and 12. How does g##g2 work??
## just pastes tokens together. It is a preprocessor directive.
E.g.
#define PASTE(a,b) a##b
int i=PASTE(1,2); /* int i=12; */
## is the preprocessor "command" for concatenating what comes before and after.
This is token pasting, described here for gcc. Token pasting is done by the preprocessor, not the compiler.
So after preprocess it will look like this:
main()
{
int var12=100;
printf("%d",var12);
}
Concatenation is being performed by the preprocessor because you used the ## command.
When you are unsure what the preprocessor is doing you can ask gcc to stop after it has run the preprocessor. Since this is before the compiler runs, the output is fairly easy to understand.
For example, assume you have a file pre.c
#define FOO 123
#define CONCAT(x,y) x##y
#define STRING(x) #x
void main()
{
int a = FOO;
int b = CONCAT(123,4567);
char* c = STRING(IGetQuoted);
}
You can produce the preprocessor output by passing the -E option to gcc.
$ gcc -E pre.c
# 1 "pre.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "pre.c"
void main()
{
int a = 123;
int b = 1234567;
char* c = "IGetQuoted";
}
Keep in mind that #include will pull in the contents of the file it specifies and can make the preprocessor output rather long.