Page 1 of 1
C pointers
Posted: Sat Jul 09, 2011 5:29 pm
by mark3094
Hi,
I've been trying to understand the va_arg macro source (compiler is Visual Studio 10, on 32-bit x86).
I have found source code on the net:
Code: Select all
#define va_arg(ap, t) (*(t *) ((ap += intsizeof(t)) - intsizeof(t)))
I have tired the code, and it works, but I want to be able to understand how it works. I'm having problems figuring out why the size of the type (t), for example and integer (4) is added to ap, and then subtracted again.
Can anyone help me to understand why this is?
For reference, this is the intsizeof macro:
Code: Select all
#define intsizeof(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
Re: C pointers
Posted: Sat Jul 09, 2011 5:54 pm
by Combuster
To break it up into steps:
Round x down to a multiple of n
x - (x % n)
Now to round x up rather than down, there are n-1 cases that need correcting, all cases that are not a multiple of n already. Try a few actual numbers to see why it works:
(x + n - 1) - ((x + n - 1) % n)
if n is a power of two, binary operations can be substituted
(x + n - 1) - ((x + n - 1) & (n - 1))
removing some bits is the same as keeping the other bits:
(x + n - 1) & ~(n - 1)
now what is rounded up to what?
((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1))
now for the other macro:
we want
x
that's the same as
x + n - n
which yields the same value as
x += n - n
with the only difference is that x is changed.
In other words: modify x, return the original.
Re: C pointers
Posted: Sat Jul 09, 2011 6:40 pm
by mark3094
Thankyou for your help.
I have a shaky understanding, so let me try explaining it back to see if I have it right.
There are two purposes to this code:
1. Return the value in the ap pointer
2. Update ap to the next value for next time it is accessed
(ap += intsizeof(t))
This updates ap to the next value for the next time the pointer is accessed, satisfying point 2
((ap += intsizeof(t)) - intsizeof(t))
This as a whole updates ap (as shown above), but subtracts the size of the current value (t) so it can return a pointer to the current data
I think I have that sorted out in my head now. Even just writing it down helps
Thanks again
Re: C pointers
Posted: Sat Jul 09, 2011 7:56 pm
by Owen
Note that this is completely 32-bit x86 specific. AMD64 (both MS and SystemV ABIs), PowerPC, SPARC and ARM (among others) have ABIs which require the compiler to implement varargs support using intrinsics.