Homebrew C Language #Define Preprocessor Directive

HackingNewbie

Well-Known Member
OP
Member
Joined
Dec 29, 2016
Messages
536
Trophies
0
Location
Somewhere in 2008
XP
699
Country
United Kingdom
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?
@QuarkTheAwesome @BullyWiiPlaza
 
Last edited by HackingNewbie,

VitaType

Well-Known Member
Member
Joined
Jul 16, 2016
Messages
1,043
Trophies
0
XP
1,457
Country
Germany
Look up what are function pointers in C then it should be understandable to you what's going on.
0x0102A3B4 is the adress of a function.
 
Last edited by VitaType,

The Real Jdbye

*is birb*
Member
Joined
Mar 17, 2010
Messages
23,283
Trophies
4
Location
Space
XP
13,838
Country
Norway
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.
 
Last edited by The Real Jdbye,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    K3Nv2 @ K3Nv2: https://youtube.com/shorts/WOppJ92RgGU?si=KE79L6A_3jESsGQM