Built-in functions, as the name indicates, are limited to functional tasks, the execution of some code.
Macros have a much wider application that they can expand, for example, into declarations or replace entire language constructs. Some examples (written for C and C ++) that cannot be performed using functions:
typedef struct POD { double a; unsigned b } POD; #declare POD_INITIALIZER { 1.0, 37u } POD myPOD = POD_INITIALIZER; #define DIFFICULT_CASE(X) case (X)+2 :; case (X)+3 #define EASY_CASE(X) case (X)+4 :; case (X)+5 switch (a) { default: ++a; break; EASY_CASE('0'): --a; break; DIFFICULT_CASE('A'): a = helperfunction(a); break; } #define PRINT_VALUE(X) \ do { \ char const* _form = #X " has value 0x%lx\n"; \ fprintf(stderr, _form, (unsigned long)(X)); \ } while (false)
In the context of C ++, Boost has many examples that are more attractive and useful.
But since with such macros you somehow expand the language (not necessarily, the preprocessor is part of it), many people do not like macros, especially in the C ++ community, a little less in the C community.
In any case, if you use such constructions, you should always be very clear about what you need to achieve, to document well and to fight the temptation to confuse your code.
Jens gustedt
source share