#include <stdio.h>
#include <stdlib.h>
struct someStruct {
int ivar;
char cvar;
float fvar;
};
main(argc,argv)
const char** argv;
{
struct someStruct someObj;
someObj.ivar = 1;
someObj.fvar = 2.3;
someObj.cvar = 'r';
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
}
This is a program I wrote which tries to access the address of fvar
by adding 4 to the address of char.
I know the concept of slack-byte. I tried to access that memory, and lo! it printed the address correctly.
printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));
Both print the same address.
Then I tried to access fvar in the following way:
printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);
and
0.000000
2.300000
were my results.
Then I realised that char* and float* are interpreted differently.
So, I tried all kinds of typecasting from char* to float* to float and also from char to float* to float and that too at all possible points like for e.g., typecasting the returned address to float
,using 4.0
instead of 4
(which I realised wasn't supposed to work... and it didn't),etc.
It somehow just doesn't print 2.300000
and keeps printing 0.000000
Where am I missing the concept?
Note that I have a 64-bit MinGW
and adds slack-byte
(I know some don't) which I've already verified by:
printf("%u",sizeof(someObj.ivar));
printf("%u",sizeof(someObj.fvar));
printf("%u",sizeof(someObj.cvar));
printf("%u",sizeof(someObj));
which yields 4
, 4
, 1
and 12 ....(sizeof(char) + 3)
respectively.
P.S. I know this is a horrible idea, but this is how I usually learn concepts XD
Assuming that the following is true:
&someObj.cvar + 4 == &someObj.fvar
you can cast the pointer value to a proper type:
printf("%f\n", *(float*)((&someObj.cvar) + 4));
(&someObj.cvar)
is a pointer to char
, so *(&someObj.cvar)
is a char
. The %f
printf
specifier expects a double
or a float
, passing a char
is invalid. Note: float
when passed in variadic functions as one of the arguments in ellipsis parameter is implicitly converted to double
, see ex. cppreference implicit conversions. You have to pass a double
or a float
to %f
, not a char
.
Notes:
main(argc,argv)
const char** argv;
{
Don't use implicit int
declaration and old, deprecated, obsolete style of function declaration. Use the normal style:
int main(int argc, char **argv) {
printf("%u\n",&someObj.fvar);
is undefined behavior. The %u
expects unsigned char
, not float *
. You can print a void*
pointer using %p
specifier: printf("%p\n", (void*)&someObj.fvar);
or cast it to unsinged int
: printf("%u\n", (unsigned int)(uintptr_t)(void*)&someObj.fvar);
C has an macro offsetof
declared in stddef.h
to access the number of "slack-bytes" (I like the name "padding bytes" better). You can: printf("%f", *(float*)((char*)&someObj + offsetof(struct someStruct, fvar)));