Reputation: 56
I was playing with structs and trying to get their values using offsets, this is my code
#include <stdio.h>
#include <stddef.h>
typedef struct abcd{
int a,b;
double c,d;
}abcd;
int main()
{
abcd teste = {.a = 3, .b = 5, .c = 7, .d = 9};
printf("value of a: %d //value of b: %d\n",*( (char*) &teste), *((char*) &teste + offsetof(abcd, b)) );
return 0;
}
output: value of a: 3 //value of b: 5
everything works fine but when I change the printf to
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
//No casting to (char*) in value of a
I get the output: value of a: 5 value of b: 1360854088
Why does this happens?
Upvotes: 1
Views: 102
Reputation: 172
printf %d but you pass sturct adcd, this is a undefined action, result is undefined,it should consider printf.c implement.
my code:
typedef struct abcd{
int a,b;
double c,d;
}abcd;
int main()
{
abcd teste = {.a = 3, .b = 5, .c = 7, .d = 9};
printf("value of a: %d //value of b: %d\n",*( (char*) &teste), *((char*) &teste + offsetof(abcd, b)) );
printf("%d\n", offsetof(abcd, b));
printf("value of a: %p value of b: %p\n", ( &teste), ((char*) &teste + offsetof(abcd, b)) );
printf("value of a: %d value of b: %d\n", teste, *((char*) &teste));
printf("value of a: %p value of b: %p\n", &teste, ((char*) &teste));
printf("value of a: %d value of b: %d\n", teste, *((char*) &teste));
//No casting to (char*) in value of a
return 0;
}
result:
value of a: 3 //value of b: 5
4
value of a: 0x7fff86f203b0 value of b: 0x7fff86f203b4
value of a: 3 value of b: -2114388464
value of a: 0x7fff86f203b0 value of b: 0x7fff86f203b0
value of a: 3 value of b: -2114388464
undfined process cause unkonwn result
Upvotes: 0
Reputation: 365950
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
This passes teste
by value, which takes more space than a single int. The 2nd %d
will probably be getting input from some of the bytes of the first arg. Compiler warnings make this clear:
$ clang-3.5 -Wall bad-printf.c -O3
bad-printf.c:12:48: warning: format specifies type 'int' but the argument has type 'abcd' (aka 'struct abcd') [-Wformat]
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
~~ ^~~~~~~~~~
$ gcc -Wall bad-printf.c -O3
bad-printf.c: In function ‘main’:
bad-printf.c:12:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘abcd’ [-Wformat=]
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
^
$ ./a.out
value of a: 5 value of b: 0
$ uname -a
Linux tesla 3.19.0-22-generic #22-Ubuntu SMP Tue Jun 16 17:15:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
It also passes a one-byte character to printf
, as the 3rd arg (2nd arg after the format string). The other bytes in the register (or on the stack, if you compiled for obsolete 32bit x86) may be leftover from something else.
Check the assembly output. You'll probably find a one-byte load from &abcd.b
, leaving the other bytes untouched.
You've told printf (by using %d
) that you passed it a full int
. If you only wanted to print an 8bit integer (so it wouldn't treat the padding as data), you need a size prefix to your format specifier.
Upvotes: 2