问题
How would I test/expand all the function macros, in a C/C++ file, without running it through a preprocessor? For example, is there a program or method which would change this:
#include <iostream>
#define AAA(a) cout << "function " << a << endl
using namespace std;
int main(){
AAA(12);
}
into this?
#include <iostream>
using namespace std;
int main(){
cout << "function " << 12 << endl;
}
I don't want to run through preprocessor because all the includes in the files make the "gcc -E <>" output really ugly, I just want a couple simple macro expansions without all the overhead.
回答1:
No, it's not possible. Your included headers could include macros that you want to expand in the body, for example. Or did you mean to not expand any macros that come from headers? The preprocessor has absolutely no way of distinguishing what you want from what you don't want in this case.
If you know in advance this is not the case, then I recommend simply writing a script to remove the includes and then run that through the preprocessor.
回答2:
I heard all possible negative answers on the topic:
- macros can only be expanded not evaluated
- processor should parse also include files
- nested macros can be over-complicated
- conditional preprocessing can be tricky
- macros are evil just avoid them
- etc etc....
They are all true, but IMO they collide with the reality of everydays programming.
In fact, working on old C project where macros were mostly simply used as functions this became of crucial importance for me. Generating all preprocessed files with /P works but is overkilling and time taking. I just needed a tool that expands a simple macro defined a few lines above or at maximum in other file.
How to do that?
1 Onl,inux simply use GDB and his expand macros capabilities 2 On windows I use https://www.jetbrains.com/resharper-cpp/ integrated into Visual Studio
So, Yes, in a practical sense, it is possible.
回答3:
Protect the #include
s from getting expanded, run the preprocessor textually, remove the # 1 "<stdint>"
etc. junk the textual preprocessor generates and reexpose the protected #include
s.
This shell command does it:
sed 's|^\([ \t]*#[ \t]*include\)|magic_fjdsa9f8j932j9\1|' | cpp | \
sed 's|^magic_fjdsa9f8j932j9||; /^# [0-9]/d'
as long as you keep the include word together instead of doing crazy shit like
#i\
ncl\
u??/
de <iostream>
(above you can see 2 backslash continuation lines + 1 trigraph (??/ == \ ) backslash continuation line).
If you wish, you can protect #if
s #ifdef
s #ifndef
s #endif
s and #else
s the same way.
回答4:
Suppose you want to see file.c. If it contains the function main, you would need to change the name of that function for this to work. The following prints the file to stdout, only with moderate added ugliness.
#include "file.c"
#include <stdio.h>
#define X(...) #__VA_ARGS__
void print_file( char* s )
{
// a loop here to move through s until some identifier is found
// in the original file, say a comment that says: //___START___HERE___
while(*s){
if( *s=='{' | *s=='}' | *s=='#' ) printf("\n");
printf("%c",*s);
if( *s==';' ) printf("\n");
}
}
int main(int argc, char* argv[])
{
print_file(X(
#include "file.c"
));
return 0;
}
来源:https://stackoverflow.com/questions/28932534/expand-c-c-function-macros-without-preprocessor