0

I'm currently working on some project as a C Developer in a company, and in our code there are many large function declarations for a different types of handling (such as state machine callbacks, event callbacks, timers etc.) and every type of handler declaration has the same semantics, for example event handler: static void onEvent1(Event event, EventArgs *args);.

There can be very big amount of such handlers and with many parameters in brackets, so I've decided to replace it with a small macro to increase readability and ease code writing like this: #define EVENT_HANDLER(funcName) static void funcName(Event event, EventArgs *args)

So the example code would look like this:

without #define :

static void onEvent1(Event event, EventArgs *args);
static void onEvent2(Event event, EventArgs *args);
static void onEvent3(Event event, EventArgs *args);

with #define :

EVENT_HANDLER(onEvent1);
EVENT_HANDLER(onEvent2);
EVENT_HANDLER(onEvent3);

After I've added changes to a code with such macro, I've heard a lot of critics from my colleagues in my address with no clear reason why it is not good. I've googled for an answer, and as far as I understand, such text replacing macro can do no harm nor lower code understanding. So, can somebody bring a clarity to me: is it really a bad habit to use #define in such a way, or no, and most impornantly: WHY?

thanks)

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    Possible duplicate of [Why are preprocessor macros evil and what are the alternatives?](https://stackoverflow.com/questions/14041453/why-are-preprocessor-macros-evil-and-what-are-the-alternatives) – user0042 Oct 02 '17 at 10:46
  • @StoryTeller Of course I know about the usage of `static` in c. – user0042 Oct 02 '17 at 10:48
  • @user0042 I've read this topic a few hours ago. I'm aware that using function-like macros is bad and why it is so. But in this post is also an example of beneficial usage of macro as function wrapper: `#define malloc(x) my_debug_malloc(x, __FILE__, __LINE__)` what is in the same manner that I did in my example. So what's the differences that makes my approach bad? – Maxim Rybalsky Oct 02 '17 at 13:40
  • "is it really a bad habit to use #define in such a way," Yes, per your group's coding standards. This is a _style_ issue (C allows a wide variety of coding styles) and such issues belong in your group's coding style guide. You will not find universal agreement that your style is better, worse, wrong or right - just tendencies. If your group lacks a written style guide - that is the biggest mistake - make one. New group member lack clairvoyance of other members minds yet can read the local style guide. – chux - Reinstate Monica Oct 02 '17 at 16:24

1 Answers1

2

You can just use a regular typedef to be type safe. It avoids the pitfalls of the pre-processor and doesn't require inventing your own language within a language. Your colleagues have a point.

typedef void EventCB(Event, EventArgs *);

And use it as you'd expect:

static EventCB onEvent1;
static EventCB onEvent2;
static EventCB onEvent3;

You'll need to repeat the prototype when defining the functions, but the compiler will do type checking and warn you of any mistakes. Another plus of working with the type system, is the ability to use the same type to declare pointers:

EventCB *func_ptr = &onEvent1;
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • That's something completely different. – user0042 Oct 02 '17 at 10:47
  • That makes things look very misleading - it makes them look more like variables. – Chris Turner Oct 02 '17 at 10:48
  • @ChrisTurner - Not as eyebrow raising as a macro (that's a matter of opinion though). Naming also plays a part in differentiating variables from functions. – StoryTeller - Unslander Monica Oct 02 '17 at 10:50
  • 1
    @StoryTeller Can you please tell more about what exact pitfalls could be in case of using macro in this manner? It's just text replacing one. Is it hard to use/understand/support it by other developers? – Maxim Rybalsky Oct 02 '17 at 12:10
  • @MaximRybalsky - [One pitfall](https://stackoverflow.com/questions/10820340/the-need-for-parentheses-in-macros-in-c), for instance. I'm not saying macros aren't useful, but given their quirks, and how divorced they are from the type system, I wouldn't use them unless I had to. Furthermore, anybody reading your code will have to refer to the definition of the macro. It's not something that's "pure idiomatic C". It's just syntactic sugar you created spare yourself typing. It's never good to complicate something *just* to spare ourselves typing. – StoryTeller - Unslander Monica Oct 02 '17 at 12:14
  • 1
    @StoryTeller, ok, thank you for your answer, It is useful since I will consider using `typedef void EventCB(Event, EventArgs *);`. But I still do not completely see why my approach is bad – Maxim Rybalsky Oct 02 '17 at 13:09