Can someone please help me understand how does following logic resolves in obtaining product of a and b?
int getProd(int a, int b){
return (uintptr_t)&((char (*) [a])0x0)[b];
}
Can someone please help me understand how does following logic resolves in obtaining product of a and b?
int getProd(int a, int b){
return (uintptr_t)&((char (*) [a])0x0)[b];
}
Suppose we have a pointer p, which points to objects of size a.
If we then say p + b, we're asking for a pointer to the b'th object past where p points.
So the actual new pointer value (on a byte-addressed machine, anyway), is going to be scaled by a, that is, the size of the pointed-to objects. That is, "under the hood", the compiler is going to do something more like p + b * a.
So we can see the multiplication a * b is happening -- but then it's getting added to the original value of p.
So if we use an initial value of 0, we'll get just a * b. And that's what the hacky getProd function is doing.
Let's break it down:
0x0
The value 0, also known in pointer contexts as a null pointer. [Footnote: there's more complexity to this definition, but let's not worry about that for the moment.]
char (*) [a]
This is a type: "pointer to char array of size a.
(char (*) [a])0x0
This is a cast: take that null pointer, cast it to the type "pointer to array [a] of char".
((char (*) [a])0x0)[b]
Take that pointer, imagine it points to an array, and fetch the b'th element of that array. Since array indexing is the same as pointer arithmetic, this will end up computing 0 + a * b.
&((char (*) [a])0x0)[b];
We had a reference to the b'th element of the "array". Now compute a pointer to that element. That pointer should literally have the value 0 + a * b.
(uintptr_t)&((char (*) [a])0x0)[b];
Finally, take that pointer and cast it to an integer type.
Now, with all of this said, it must be pointed out that this is a hack. Writing code to perform arithmetic on null pointers in this way is highly problematic. It might be almost-but-not-quite-legal; it might be legal-but-just-barely-legal. You could argue for hours about which side of the line the answer falls on.
In this case, of course, it's an academic argument, because no one would ever seriously propose doing multiplication this way.
This code invokes undefined behavior by performing pointer arithmetic on an invalid pointer. That being said, here's what it's attempting to do.
(char (*) [a])0x0 is casting the value 0 to a pointer to an array of size a of char, giving you a pointer to an object that takes up a bytes.
Then with &((char (*) [a])0x0)[b] it uses array indexing to get the b element this pointer points to and takes its address.
Also, because an expression of the type E1[E2] is exactly the same as *(E1 + E2), this means the prior expression is the same as &(*((char (*) [a])0x0) + b), and because & followed by * cancel out this is the same as ((char (*) [a])0x0) + b. So there's no dereferencing of an invalid pointer.
Because pointer arithmetic increments the value of a pointer by the offset times the element size, you now have a pointer whose numeric value is a*b. That value is then converted to an integer type and returned.
Where the undefined behavior comes into play is in the implicit + operator in the array indexing. Pointer arithmetic is only valid if the original pointer and the result of the addition both point to valid object (or one element past the end of an array of objects). Since 0 is not a valid address, this is UB.
Technically this is undefined behavior. But the intended functionality that this code might resolve assuming a naive compiler logic is as following.
((char (*) [a])0x0) - this takes an address 0x0 and is casting it to a pointer to array of a char elements, that is a pointer to an object of size a bytes.
Now, according to C pointer arithmetic any operation (addition/subtraction) with this pointer will be performed in the multiples of a.
Next, it is taking the b offset of this pointer. As we know, p[b] is equivalent to *(p + b) for any pointer p. In our case p is equal to 0x0 and is a pointer to an object of size a. Therefore p + b will have a numerical value of 0x0 + b * sizeof(*p) or 0x0 + a * b. Which is exactly a * b.