1

I came across a c++ code where a function was defined in the header section of the file as follows

#define APPEND_VALUE(X, Y, I)\
{\
  int idx = (Y*100+X);\
  int idxn = idx + ValueCount[idx];\
  TempVector[idxn] = I;\
  CountVector[idx] += 1;\
}

(Note that this is not all the code and TempVector and CountVector was defined elsewhere)

Later in the code APPEND_VALUE was used like any other function. I was wondering what is the difference between the above (#define APPEND_VALUE) code and the below code

void APPEND_VALUE(int X, int Y, int I)
{
  int idx = (Y*100+X);
  int idxn = idx + ValueCount[idx];
  TempVector[idxn] = I;
  CountVector[idx] += 1;
} 

What is the advantage of using one over the other? also is there a technical name for defining a function as show in the first code(the one using #define).

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Mc Missile
  • 715
  • 11
  • 25
  • 6
    the first version does not work for `APPEND_VALUE(5, 2+3, 5);`. – mch Jul 09 '18 at 10:50
  • 4
    The #define version is still a macro. The code is expanded at the invocation site. It has all the expected problems (with macros) including namespace pollution and unexpected parameter behaviour. – Richard Critten Jul 09 '18 at 10:52
  • 2
    @mch: But judicious use of parentheses could address that. – Scott Hunter Jul 09 '18 at 10:52
  • Preprocessor *macros* (which is what you have, not functions) are *expanded* before the parser of the compiler sees the code. So when the preprocessor sees `APPEND_VALUE(...)` (with proper arguments of course) then it basically *replaces* that with the body of the macro. Most compilers have options to let you see the code after preprocessing, I suggest you do that to see how the macro have been expanded. – Some programmer dude Jul 09 '18 at 10:53
  • See also [here](https://stackoverflow.com/q/9104568/9593596) - though tagged C and not C++, the explanation might provide just the right info for your situation, too. – lubgr Jul 09 '18 at 10:53
  • Also, macros are not type-safe and generally tend to make code harder to read, understand and maintain. – Some programmer dude Jul 09 '18 at 10:54
  • 3
    Possible duplicate of [Macro vs Function in C](https://stackoverflow.com/questions/9104568/macro-vs-function-in-c) – Caleth Jul 09 '18 at 11:00
  • Beside the fact that today, using MACROs is bad, the code inside the macro will be inserted where the macro is used which can lead to bigger executable sizes but also faster code. When you use a function then the compiler will decide if he will blow up the code size for performance reasons or not. So when the code is very old this was maybe an performance improvement. – user743414 Jul 09 '18 at 11:54

1 Answers1

1

#define is part of something called the "preprocessor." Essentially, this is the code that is processed before the C document is compiled. Most of the preprocessor code is in a file with a ".h" extension (which is why you may have seen that when importing libraries).

The preprocessor language is primitive. For example, if it performs a "textual substitution [with] missing parentheses", the result of the preprocessor function may not be what you intended it to return (credit: @Deduplicator). Take a look at this post for an example: #define Square(x) (x*(x)). For this reason, and many others, I would prefer coding it in the regular C language when possible (just note there are many cases where the preprocessor may be faster and more helpful). Hope this helps!

kamykam
  • 300
  • 2
  • 11
  • 1
    "...there are many cases where the preprocessor may be more faster and helpful" Any example? – jszpilewski Jul 09 '18 at 11:26
  • 1
    Lexical binding of expressions is the least of your concerns. Side effects are the real problem. – StoryTeller - Unslander Monica Jul 09 '18 at 11:44
  • @jszpilewski, in response to your question: A good example of where the preprocessor can be helpful is when you prove your code with contracts. For example, you may insert thousands of assert statements during production. But after the code is complete, you want to get rid of all the assert statement (to save processing power). You can redefine ASSERT in the preprocessor to do nothing (rather than individually get rid of all the assert statement). This will also allow you to use the assert statements later, if need be – kamykam Jul 10 '18 at 10:28
  • 1
    Since when does the preprocessor disdain operator-precedence? – Deduplicator Aug 15 '18 at 14:24
  • @kamykam That's not about operator-precedence, but textual substitution, a completely different thing. – Deduplicator Aug 15 '18 at 15:19
  • @Deduplicator My fault, I misunderstood your question. I'm not sure about the answer to that one... – kamykam Aug 15 '18 at 15:49
  • So, are you going to fix your answer? – Deduplicator Aug 15 '18 at 16:35
  • @Deduplicator Yes, I'll fix it. Thank you for bringing it to my attention – kamykam Aug 17 '18 at 20:01
  • The preprocessor never performs incorrect order of operations. What you are observing is instead primitive textual substitution combined with missing parentheses. – Deduplicator Aug 17 '18 at 21:08
  • @Deduplicator thank you for your reply, and I apologize for my misunderstanding. I've fixed it and cited you. – kamykam Aug 18 '18 at 23:47