0

How can I use macros as function pointers? I have no idea to solve this. I created a sketch (doesn't work, full of syntax errors) to show what I try to accomplish. Please help!

#define D0_OUT(x) (x/1024*100) //I want to use this for Pin0 calculation
#define D1_OUT(x) (x*1024) //I want to use this for Pin1 calculation

struct Pin {
  CalcMethod *calcMethod; //int methodName(int x) { return MACRO(x); }

  Pin(CalcMethod *calcMethodParam) {
    calcMethod = calcMethodParam;
  }

  int calc(int x) {
    return calcMethod(x);
  }
};

#define PIN_COUNT 2
Pin *pins[PIN_COUNT];

void start() {
    pins[0] = new Pin(D0_OUT); //use the D0_OUT macro to calculate
    pins[1] = new Pin(D1_OUT); //use the D1_OUT macro to calculate
    int pin0CalcResult=pins[0]->calc(5); // =5/1024*100
    int pin1CalcResult=pins[1]->calc(6); // =6*1024
}
Quentin
  • 62,093
  • 7
  • 131
  • 191
Péter Aradi
  • 370
  • 1
  • 4
  • 12
  • 3
    You are asking the wrong question. The correct answer is "don't you macros, use functions". Try to avoid all `#define`. Use normal constants and normal functions. – Sulthan Dec 24 '17 at 10:00
  • 3
    A macro is a piece of text. You cannot use a macro as a function pointer just like you cannot use the word "oven" to heat a pizza. – n. m. could be an AI Dec 24 '17 at 10:02

3 Answers3

3

Macros are handled by the preprocessor. They don't exist in the compiled code, therefore there is no pointer.

There is one rule you should follow in modern code and that rule is "don't use macros for furnctions". Macros for functions are a relict that still has some good uses but they are very rare.

Just declare a normal function

int do_out(int x) {
    return x / 1024 * 100;
}

Also see "static const" vs "#define" vs "enum"

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • There's nothing "old" or "bad" about macros if you know where to use them. That applies to any language feature, really (even `goto`) — blindly advocating "never use this" is spreading FUD. – aaaaaa123456789 Dec 24 '17 at 10:05
  • @aaaaaa123456789 As I said, there are some rare uses but they are almost unnecessary in modern C/C++ and they bring a lot of problems. There are hard to write correctly (parentheses) and they are not type safe. – Sulthan Dec 24 '17 at 10:07
  • C and C++ are very different beasts. Type safety in C is often not a problem at all (again, depends on how careful you are and what your code does — unlike C++, all types in C that can appear in typical expressions are ultimately numbers, after all), and having to wrap an expression in parentheses is not enough to completely ignore a language feature. Re: your edit, using macros for functions is rare, but it does have its place in a few simple cases. – aaaaaa123456789 Dec 24 '17 at 10:12
  • @aaaaaa123456789 I removed the bit about constants because the longer I don't work in C, the more I forget its little problems. I will still oppose using macros for functions. – Sulthan Dec 24 '17 at 10:14
  • Consider this case: `#define triple(num) (num * 3)`. (Why you'd need a function/macro to triple a number is a separate question.) The macro, as written, can be applied to numbers of any type and will result in a value of the same type, bar integer promotion — in particular, it works equally well for integers and floats. You cannot do that with a function. – aaaaaa123456789 Dec 24 '17 at 10:18
  • @aaaaaa123456789 Macros for functions are a relict. They come from an age when some things were impossible (or hard) to express in plain code and when the compiler was very very different. Macros impact speed of compilation a lot, for example. Also, from code mantainance perspective, the type safety is important. Macros introduce bugs that are very hard to find. – Sulthan Dec 24 '17 at 10:19
  • @aaaaaa123456789 A simple example and you have written the macro incorrectly. You would have to wrap `num` into parentheses too. See my meaning? – Sulthan Dec 24 '17 at 10:20
  • I'm well aware extra parentheses are necessary (I usually end up with three or four levels of them when writing macros); I was trying to show a simple example and opted for clarity. And my point stands that there is no way to write a function equivalent to that macro, compiler improvements notwithstanding (since this is built into the definition of the language). Again, this is C, not C++ (where templates exist and type safety is much more of a concern). – aaaaaa123456789 Dec 24 '17 at 10:22
  • @aaaaaa123456789: You can use template function: `template decltype(auto) triple(const T& value) { return 3 * value; }` – Jarod42 Dec 24 '17 at 12:22
  • @Jarod42 Isn't that C++? – Sulthan Dec 24 '17 at 12:34
  • @Sulthan: Yes it is C++. I might have miss some part of the discussion about C... – Jarod42 Dec 24 '17 at 12:49
  • @Jarod42 this is why I explicitly mentioned "this is C, not C++" in my previous comment, and referenced C++'s templates. (I'm not quite sure of why you're using a `const T&` instead of just a `T`, but then again, I only know C++ superficially.) C and C++ aren't the same, and the way they handle data types is completely different — which is why something that is a good idea in C can be a bad practice in C++. – aaaaaa123456789 Dec 24 '17 at 14:54
0

You can, but not advisable, use macros as named lambdas. Thus

#define D0_OUT [](int x) { return x / 1024 * 100; }
#define D1_OUT [](auto x) { return x * 1024; }

and it should work.

D0_OUT example usable in C++11 and D1_OUT usable with C++14.

Bo R
  • 2,334
  • 1
  • 9
  • 17
0

I know this is an old thread..

Assuming that you cannot just change the macro to be a function. Maybe it is part of a driver of library somewhere and you need to pass it into another function for some reason like unit testing. You can just wrap the macro within your .c file where you want to use it.

So this:

#define D0_OUT(x) (x/1024*100) //I want to use this for Pin0 calculation

becomes:

static int D0_OUT_wrapper(int x)
{
    return D0_OUT(x);
}

So wrapper goes in like normal:

pins[0] = new Pin(D0_OUT_wrapper);

If you have full control of the code you are writing then just don't use macros.

Tim Ashton
  • 436
  • 6
  • 18