![]() |
Tutorial Variable arguments in C (or C++) - Printable Version +- Sinisterly (https://sinister.ly) +-- Forum: Coding (https://sinister.ly/Forum-Coding) +--- Forum: C, C++, & Obj-C (https://sinister.ly/Forum-C-C-Obj-C) +--- Thread: Tutorial Variable arguments in C (or C++) (/Thread-Tutorial-Variable-arguments-in-C-or-C) |
Variable arguments in C (or C++) - phyrrus9 - 10-09-2016 If you've ever wondered how printf can magically take as much as you throw at it (hehe), it isn't some compiler magic happening here. What's really happening is called variable arguments. When a function is called in C (in most cases, Borland, fuck you), it passes the first 4 integer arguments (or pointers) in registers (which vary by system). After that, it pushes them to the stack in reverse order. Once inside the function, you can access them by knowing the stack offset, frame level, and variable offset. Now, that all sounds pretty tricky, and it really is a pain in the ass to do, so there is a set of helper macros in stdarg.h (new C, don't worry about old stuff, your compiler doesnt support it anymore). EDIT: I have pastebinned all of the code to make SL happy Here's what you need to take an infinite number of arguments:
An example for this is a simple printf definition: Code: void myprintf(const char * ...); the important thing to watch there is the three dots after the first argument. This tells the compiler NOT to use the standard ABI, and to push ALL of the arguments on the stack in reverse order. This way, we don't have to determine the frame order or any of that nonsense. Alright, so we have a basic starting point, let's talk a little bit about that first argument before going into detail. We only NEED 1 argument, but we should think about what that argument actually is. We can have a near infinite number of args, but its not like passing in an array in Java where you can check the size. We don't get that courtesy, we have no clue how many args were actually provided (or what their types are). So, we should use some form of format specifier (like printf) so we know not only how many arguments but also what type they are. With that in mind, let's write a printf with the following: Code: %i -> integer We start off with our base function stuff: http://pastebin.com/fjqKCKUE Ok, so, let's explain some of those. I put in some comments to explain relatively what they meant, but I'll break it down nontheless. Code: va_list args; Code: va_start(args, fmt); Code: va_end(args); Now, we can start parsing out arguments. To do this, we will use the following macro: Code: type va_arg(list, type); So, let's write our basic code: http://pastebin.com/RtCtYJWi Ok, now, if you need to be fed what just happened there, take a look at this article We are now at the point where we can start pulling out args. Before we do that, let's make a few helper functions. These will make our myprintf code less cluttered and allow us to delegate which prints which type. http://pastebin.com/vWq8z3JH Ok, now we are ready. So, let's add in our parsing functions to our code: http://pastebin.com/5pyArn41 And there you go! I know I skimped on pointers, but there are plenty of tutorials on those, and if you need a more in-depth one, feel free to reply and let me know. |