#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.
Related
I have the following really simple header file:
#ifndef __ZYNQ_CSORT_H__
#define __ZYNQ_CSORT_H__
#define CONSTANT 5
#endif
I am including this header file in another C file in the same folder. The preprocessor doesn't complain at all about the header file include, but when I try to print the value of the constant, it tells me that it is not defined. Anybody know what's up?
When I'm uncertain about what the preprocessor is up to, I find it is often revealing to run the C preprocessor by itself. For example, given test1.h:
#ifndef TEST1_H
#define TEST1_H
/* In TEST1_H */
#define CONSTANT 5
#endif
... and test1.c:
#include "test1.h"
#include "test1.h"
int main(int argc, char **argv) {
return CONSTANT;
}
... running cpp -C test1.c test1.c.out (the -C argument makes the preprocessor retain comments) gives test1.c.out as follows:
# 1 "test1.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test1.c"
# 1 "test1.h" 1
/* In TEST1_H */
# 2 "test1.c" 2
int main(int argc, char **argv) {
return 5;
}
Thus, for my case I can be confident that the right header file is being included.
CONSTANT would be undefined if __ZYNC_CSORT_H were already defined when this file was parsed.
#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
Example =
#define a 100
#define b 200
main()
{
int c=a+b;
}
After preprocessing
Output-
#define a 100
main()
{
int c=a+200;
}
You could try refactoring the macros to allow external configuration, i.e.
/* config.h */
/* set defaults for a and b */
#ifndef a
#define a 100
#endif
#ifndef b
#define b 200
#endif
and
/* main.c */
#include "config.h"
int main(void)
{
int c = a + b;
}
Then you can set the macros externally when building, for instance like this:
$ gcc -E -Da=a main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "config.h" 1
# 4 "main.c" 2
int main(void)
{
int c = a + 200;
}
$ gcc -E -Db=b main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"
# 1 "config.h" 1
# 4 "main.c" 2
int main(void)
{
int c = 100 + b;
}
Now, of course you don't have to use a separate configuration header, but I'd recommend it from a maintenance perspective, it will make it easier to keep track of available configuration settings and their defaults.
#define a 100
#define b 200
main()
{
#undef b
int c=a+b;
}
No. What's your real goal?
If you want to do, it's better to make some script to do that.
If you don't want to preprocess a macro, just don't use it:
#define a 100
//#define b 200
int main()
{
int c = a + 200;
return 0;
}
The purpose of preprocessing is to process the preprocessing directives. I don't know of any way to keep a specific preprocessing directive, especially because the next step, compilation, doesn't know anything about these.
This is another reason why you should be careful when using macros -- when the name is found in the source, then it is substituted, no matter what:
#define a 100
main()
{
int a; // Compilation error happens here
....
}
Regarding Peter Miehle's answer, unifdef can be used to partially process #if and #ifdef directives, but it cannot be used to selectively expand macros. See http://dotat.at/prog/unifdef
I'm trying to do something that is conceptually similar to this, but can't seem to get it to work (error shown at end) any ideas?
#include <stdio.h>
int main( int argc , char const *argv[] )
{
int abc_def_ghi = 42;
#define SUFFIX ghi
#define VAR(prefix) prefix##_def_##SUFFIX
printf( "%d\n" , VAR(abc) );
return 0;
}
// untitled:8: error: ‘abc_def_SUFFIX’ undeclared (first use in this function)
You just need additional indirection:
#include <stdio.h>
int main( int argc , char const *argv[] )
{
int abc_def_ghi = 42;
#define SUFFIX ghi
#define VAR3(prefix, suffix) prefix##_def_##suffix
#define VAR2(prefix, suffix) VAR3(prefix, suffix)
#define VAR(prefix) VAR2(prefix, SUFFIX)
printf( "%d\n" , VAR(abc) );
return 0;
}
Even though it looks redundant, it's not.
The usual idiom for correctly using the stringizing (#) or token pasting (##) pre-processing operators is to use a 2nd level of indirection. (What are the applications of the ## preprocessor operator and gotchas to consider?).
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)
Then:
int main( int argc , char const *argv[] )
{
int abc_def_ghi = 42;
#define SUFFIX ghi
#define VAR(prefix) PASTE( prefix, PASTE( _def_, SUFFIX))
printf( "%d\n" , VAR(abc) );
return 0;
}
Should give you the results you're looking for.
Basically, what happens is that processing of the # and ## operators takes place before macro replacement. Then another round of macro replacement occurs. So if you want macros to be used along with those operations you have to use a 1st level that simply does the replacement - otherwise the stringizing or pasting happens first, and the macros aren't macros anymore- they're whatever the 1st round of stringizing/pasting produces.
To put it more directly - the first level of macro allows the macro parameters to be replaced, then the 2nd level of macro replacement does the stringify/token-pasting operation.
This works with sufficient levels of indirection. While another answer is plenty adequate, I want offer this chunk of code as a demo:
#define SUFFIX ghi
#define VAR1(prefix) prefix##_def_##SUFFIX
VAR1(abc)
#define VAR2_(prefix, sfx) prefix##_def_##sfx
#define VAR2(prefix) VAR2_(prefix,SUFFIX)
VAR2(abc)
#define VAR3_(prefix, sfx) prefix##_def_##sfx
#define VAR3x(prefix,sfx) VAR3_(prefix,sfx)
#define VAR3(prefix) VAR3x(prefix,SUFFIX)
VAR3(abc)
Save this is a text file, x.c, and only preprocess it.
gcc -E x.c
Observe and ponder. I don't quite understand it entirely myself. Just spend two hours trying to get a macro using stringify to work. It is interesting to see that double indirection is sometimes needed.
I know that this will not work, but hopefully you can see what I'm trying to do
#if ASSIGN_ALLOWED
#define MAYBE_SKIP_REST_OF_LINE
#else
#define MAYBE_SKIP_REST_OF_LINE ; //
#endif
char str[80] MAYBE_SKIP_REST_OF_LINE = "Hello\n";
long array[3] MAYBE_SKIP_REST_OF_LINE = { 7,8,9 };
int x MAYBE_SKIP_REST_OF_LINE = 3;
//...many many more similar lines...
Is there a way to do this such that it works?
Sure:
#ifdef ASSIGN_ALLOWED
#define OPTIONAL_INITIALISER(x) = x
#else
#define OPTIONAL_INITIALISER(x)
#endif
char str[80] OPTIONAL_INTIALISER("Hello\n");
#define ARRAY_INIT { 7,8,9 }
long array[3] OPTIONAL_INITIALISER(ARRAY_INIT);
#undef ARRAY_INIT
int x OPTIONAL_INITIALISER(3);
Any initialisers containing commas, like for array in the example, will need to be expanded from their own macro, like ARRAY_INIT in the above. If your compiler supports C99 varargs macros, then you can instead do it in a cleaner way:
#ifdef ASSIGN_ALLOWED
#define OPTIONAL_INITIALISER(...) = __VA_ARGS__
#else
#define OPTIONAL_INITIALISER(...)
#endif
char str[80] OPTIONAL_INTIALISER("Hello\n");
long array[3] OPTIONAL_INITIALISER({ 7,8,9 });
int x OPTIONAL_INITIALISER(3);
As comments are filtered out in the preprocessor run, i dont think so
It would depend on how the preprocessor worked with comments and macros. If it strips comments after macro expansion then your smooth sailing, but otherwise it might not work simply due to the preprocessor implementation.
You could try this? (it would be messy though).
#define MAYBE_SKIP(code) code
#define MAYBE_SKIP(code) /* code */
The preprocessor strips out commented sections. Try running
gcc -E source.c
This will run the preprocessor on your code but will not actually compile it, allowing you to see what happens after macro expansion. You should notice that all the comments are gone from any expanded macros.