0

Is it possible to wrap only function call with macro?

When I'm trying

#define foo(x) bar(x)

it wraps both function call and definition.

I know about wrapping function with linker, but in this case I can't use this solution.

Lets assume some code

#define foo(x) bar(z)

int foo(int z){
//some code
}

int bar(int x){
//some code
}

int function(){
int a = foo(2);
}

I want to int a = foo(2); after preprocessing become int a = bar(2). Currently I only receive "redefinition" error.

Edit: my example shows, what I want to achieve, but I in real code I have to put this macro to project via cmake file and I also can't modify source code in destination file. Sorry for not mention about it earlier.

mmichal10
  • 322
  • 2
  • 13
  • `it wraps both function call and definition` -- what? All it does is replace the string `foo(x)` with `bar(x)`. The preprocessor does not deal with definitions, that's in the compiler stage. – Patrick Roberts Feb 08 '18 at 16:54
  • 3
    Can you be more specific about what you want to achieve? – Jens Gustedt Feb 08 '18 at 16:54
  • I meant it replaces function name in foo() header, not whole definition. – mmichal10 Feb 08 '18 at 16:55
  • 2
    If you want to inhibit macro expansion at some place you'd just have to put the macro in parenthesis such as `int (foo)(void)`. – Jens Gustedt Feb 08 '18 at 16:56
  • 1
    The preprocessor deals with text, it doesn't know anything about C syntax or semantics. When it sees `foo` followed by parentheses, it replaces it. – Barmar Feb 08 '18 at 16:56
  • 1
    @JensGustedt [looking at question history](https://stackoverflow.com/q/48664718/1541563), my guess is this is for shadowing a function invocation with an alternate stub defined in an external unit-test file? Is that correct? – Patrick Roberts Feb 08 '18 at 16:58
  • See the answers from here: https://stackoverflow.com/questions/25881785/wrapping-functions-with-macros-without-renaming-c – VladP Feb 08 '18 at 17:05
  • yes, you undef it afterwards. this is a useful trick for when you have many verbose objects in one section and want to simplify them in that section. Be very mindful of the lifetime of your macros, by undefing them properly, they stop having all the evils that are often attributed to macros. be mindful that one advantage of c preprocessor over most assembly preprocessors is the ability to undef to begin with. – Dmytro Feb 08 '18 at 17:11

3 Answers3

1

use undef to manage the lifetime of your macros and not to screw with sections of code that aren't aware of your macros' existence.

int foo(int z){
//some code
}

int bar(int x){
//some code
}

int function(){
    #define foo(x) bar(z)
    int a = foo(2);
    #undef foo
}

This trick extends to things like header options, often things like Windows.h are included and the header's defines depend on defines defined outside of the header as follows:

#define WIN32_LEAN_AND_MEAN // used in ifdef checks to not define/include rarely used stuff
#define NO_STRICT // used to allow HANDLE types to be used as void * without type errors
#define NO_MINMAX // used to avoid errors because MIN/MAX are already defined
#include <Windows.h>

this pollutes scope with macros that have no use after the header finished parsing, so you can clean up by undefing them after include:

#define WIN32_LEAN_AND_MEAN // used in ifdef checks to not define/include rarely used stuff
#define NO_STRICT // used to allow HANDLE types to be used as void * without type errors
#define NO_MINMAX // used to avoid errors because MIN/MAX are already defined
#include <Windows.h>
#undef NO_MINMAX 
#undef NO_STRICT 
#undef WIN32_LEAN_AND_MEAN

This makes it easier for people reading your code, especially beginners to C to know that these are options and don't have any use after the include occurs. This also allows you to do interesting C++-like behaviors like templating based on defines defined before include, without conflicts of including headers multiple times.

Dmytro
  • 5,068
  • 4
  • 39
  • 50
  • Often `#define foo(x) bar(z)` benefits with a prior test if `foo` has a `#define`. – chux - Reinstate Monica Feb 08 '18 at 17:36
  • non naively, you should #ifdef every macro you #define, but this gets into weird annoyances like what if that macro is already defines, then you have to create another macro to keep track of the fact that you are redefining the macro, and may need to redefine it back to what it was beforehand. A way to avoid this is to generate a guid and replace "-" with underscore and prefix the guid with _, this way it's not realistically likely for collisions, but that sacrifices the benefits of short macros; I like to assume that if my macro is shorter than 3 characters, nobody but me should be using it. – Dmytro Feb 08 '18 at 20:08
  • That's why undef is important; many headers define a lot of short macros like MIN and MAX or N that are desirable macro names; almost none use lowercase macros under 3 characters in length so foo/bar/baz/a/b/c should be really safe short duration scope macros. You should test #ifdef macro before defining, and if it is, undef it if it's in use. One annoying culprit of this is CreateWindow; you might want to create a method CreateWindow inside a class, but Windows.h defines it based on whether unicode is defined or not. In cases like this I undef CreateWindow. – Dmytro Feb 08 '18 at 20:14
0

Not sure if this is what you want, but you could try putting the macro after the function declarations. So

foo(...){}
bar(...){}
#ifdef REPLACE_FOO
#define foo(x) bar(x)
#endif
main(){
    foo(1);
}
C_Elegans
  • 1,113
  • 8
  • 15
0

That's because the preprocessor does not care about which string to replace. It also replaces your original function definition foo, which means that the function bar is defined twice.

You should be able to solve that by something like that:

#if !defined(foo)
int foo(int z){
   //some code
}
#endif

Of course, it depends on what you actually want to do.

MemAllox
  • 533
  • 5
  • 22