Hello. I have been learning Wii U Homebrew development, and am confused with this use of the #define preprocessor directive:
Code:
#define OSDynLoad_Acquire ((void (*)(char* rpl, unsigned int *handle))0x0102A3B4)
and similar uses. Can someone explain what this sort of thing does?
A definition is similar to a constant variable, but not quite.
At compile time, anywhere in code the defined constant shows up, it's replaced with the contents of the definition.
Whereas a variable would not be outright replaced, it would be referenced in the compiled code.
In this case, it's basically being used to define a macro, containing the declaration of a function, so that you don't have to type out the function by hand every time or copy paste it.
This could have been done differently, simply by wrapping the function call in another function, but that would mean the CPU first has to jump to your function, then set up the parameters and jump to the OS call. It's only a few instructions difference, and in most cases won't matter, but in certain cases such as code that needs to run as fast as possible (emulators come to mind), timing sensitive code or code that runs on low end microcontrollers like atmega etc. it does matter.
Inline code like this is slightly faster, with the drawback of increasing the size of the binary.
IIRC C/C++ do support the inline keyword for functions, so that could have been used instead for exactly the same end result (likely byte for byte the same), but that's just a matter of personal preference.
It's a good idea to use definitions if you have a piece of code, a constant value, a specific declaration or anything like that that you know will be used a lot in code, or you want to be able to easily change later on.
Because it's replaced at compile time, you can use it in places where a simple variable wouldn't work.
There's also simple if/else compares you can do with definitions, which will be checked at runtime and only the code that is actually in the "correct" part of the check is included in the compiled code.
So you can have a DEBUG flag for example, and use it in your code with #ifdef so that when you compile a build you want to share with people, set #define DEBUG 0 and all your super secret debug code will be magically excluded from the binary.