Is there a way to replace C macros for normal C code

I want to run the x tool in the C file and get the post macro. (If we can only work as macros even better). I know about gcc -E , but it does everything in one large file.

Basically, I would like to use some C macros for repeating code, but I don't want the final code to contain any macros because they are not approved by the project.

+4
source share
4 answers

Using the scripting language of your choice, comment out all #include s, then run gcc -E -Wp,-P,-C,-CC foo.c , then uncomment #include s. Or you can replace #include with some line that doesn't start with # ... for example, include# or @include ; the possibilities are endless. The @ approach instead of # gives you full control over which preprocessor directives execute and don't extend ... code that you don't want to extend with @ , and then the script just runs gcc -E and then changes @ to # . However, I think it would be better to do it the other way around using a special marker (e.g. @ ) to indicate your extensible macros. Then the script will turn the leading # into something else (like HIDE# ) and turn the marker ( @ , for example) to # , run gcc -E , then turn HIDE# (or independently) back to # .

-Wp indicates preprocessor options. -P means that it does not generate line directives, -C means that you do not delete comments, and -CC means that you do not delete comments generated by macros - this means that comments in your code-generating macros will be saved to the output. To determine all the available preprocessor options (there are a lot of them, mostly not interested), run gcc -Wp,--help anyfile.c ... what I did to come up with this answer (after the first run of gcc --help to find -Wp ). (Knowing how to find things is more important than knowing things.)

+3
source

How do I add a separator to my code right after the #include list so that you can get rid of expandable file extensions manually, but after running gcc -E ?

Sort of:

 #include <one> #include <two> void delete_everything_above_and_put_includes_back(); // delimeter #define MACRO(X) ... //rest of the code 

I do not know a tool that extends macros, but does not extend #include s ...

+2
source

I decided to add another answer because it is completely different.

Instead of tricks for expanding macros to the original project repository - do you consider using alternatives to const and inline ?

Basically, these are the reasons why macros "frown" in your project.

You should remember that inline is just a “sentence” (that is, the function cannot actually be inlined), and const will use memory instead of a constant literal (well, depending on the compiler, a good compiler will optimize), but it will do two things:

  • Keep your code in accordance with the coding standards of the project (which is always good, at least politically, if not necessarily technically).
  • You won't need additional hidden scripts or actions on your behalf to keep the code reusable and supported (I assume you want to use macros to avoid re-code, right?)

Observe this as an option.

+1
source

As a possible solution to your problem: “write a macro and then discard it, replacing it with an equivalent function”, you can use prototyped macros similar to functions. They have some limitations and should be used with some caution. But they work almost the same as a function.

 #define xxPseudoPrototype(RETTYPE, MACRODATA, ARGS) typedef struct { RETTYPE xxmacro__ret__; ARGS } MACRODATA xxPseudoPrototype(float, xxSUM_data, int x; float y; ); xxSUM_data xxsum; #define SUM_intfloat(X, Y) ( xxsum = (xxSUM_data){ .x = (X), .y = (Y) }, \ xxsum.xxmacro__ret__ = xxsum.x + xxsum.y, \ xxsum.xxmacro__ret__) 

I explained the details here (mainly section 4, for macros like functions):

Macro rigging features

  • The first line defines a macro that can be used to declare pseudo-prototypes for macros.
  • The second line uses this macro to provide such a pseudo-prototype. It defines the “formal” parameters of the desired types. It contains the desired type of "return" for the macro, the name of the structure where the macro parameters will be stored, and finally, the parameters (with types!) Of the macro. I prefer to call them pseudo-parameters.
  • The third line is a mandatory statement that makes pseudo-parameters “real”. He announces the structure to be written. It defines a structure containing a "real" version of pseudo-parameters.
  • Finally, the macro itself is defined as a chained list of expressions separated by commas. The first operand is used to "load" macro arguments into "real" typed parameters. The last operand is the "return value", which also has the desired type.

Please note that the compiler makes correct and transparent type diagnostics.
(However, it is necessary to have some relation to these constructions, as explained in the link).

Now, if you can collect all the sentences of your macro as a chain of function calls, separated by commas, then you can get the function macro as you need.

In addition, you can easily convert it to a real function, since the parameter list is already defined. Type checking has already been done, so everything will work fine. In the above example, you need to replace all lines (except the first) with the following:

 #define xxPseudoPrototype(RETTYPE, MACRODATA, ARGS) typedef struct { RETTYPE xxmacro__ret__; ARGS } MACRODATA float SUM_intfloat(int x, float y) { /* (1) */ xxPseudoPrototype(float, xxSUM_data, int x; float y; ); /* (2) */ xxSUM_data xxsum; /* (2) */ return /* (3) */ ( xxsum = (xxSUM_data){ .x = x, .y = y }, /* (4) (5) (6) */ xxsum.xxmacro__ret__ = xxsum.x + xxsum.y, /* (5) (6) */ xxsum.xxmacro__ret__) /* (6) */ ; /* (7) */ } /* (8) */ 

The replacement will follow the system procedure:

(1) The macro header has turned into a function header. Semicolons (;) are replaced by commas (,).
(2) The declaration lines move inside the function body.
(3) Added the word "return".
(4) Macro arguments X, Y, are replaced by functional parameters x, y.
(5) All trailing "\" s are deleted.
(6) All intermediate calculations and function calls remain intact.
(7) Added semicolon. (8) The body of the closing function.

Problem:. Although this approach solves your needs, note that the function duplicates its parameter list. This is not good: pseudotrotypes and duplicates should be removed:

 float SUM_intfloat(int x, float y) { return ( x + y ) ; } 
0
source

All Articles