Macros, and any other directive prefixed with a #
are processed before C compilation by the pre-processor; they do not generate any code, but rather generate source code that is then processed by the compiler as if you had typed in the code directly. So in your example the code:
int main()
{
CALL_FUNCS(2) ;
}
Results in the following generated source code:
int main()
{
do { \
func1(2);
func2(2);
func3(2);
} while (0) ;
}
Simple as that. If you never invoke the macro, it will generate exactly no code. If you invoke it multiple times, it will generate code multiple times. There is nothing clever going on the macro is merely a textual replacement generated before compilation; what the compiler does with that depends entirely on what the macro expands to and not the fact that it is a macro - the compiler sees only the generated code, not the macro definition.
With respect to const vs #define, a literal constant macro is also jyst a textual replacement and will be placed in the code as a literal constant. A const
on the other hand is a variable. The compiler may simply insert a literal constant where that generates less code that fetching the constant from memory, in C++ that is guaranteed for simple types, and it would be unusual for a C compiler not to behave in the same way. However, because it is a variable you can take it's address - if your code does take the address of a const
, then the const
will necessarily have storage. Whether that storage is in RAM or ROM depends on your compiler and linker configuration - you should consult the toolchain documentation to see how it handles const storage.
One benefit of using a const
is that const variables have strong typing and scope unlike macros.