Reputation: 2337
The Code used
#include<stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s1;
int main()
{
printf("%p %p \n",(&s1.b)-1, &s1);
}
If I print the address of &s1.b
it prints 0x804a01c
and &s1.b-2
prints 0x804a018
why it is printing same address 0x804a01c
if i select &s1.b-1
?
Upvotes: 0
Views: 1455
Reputation: 241779
Thank you for posting your code. Now I see the issue. It is because of padding. To wit:
printf("sizeof(char): %d\n", sizeof(char));
printf("sizeof(short): %d\n", sizeof(short));
printf("sizeof(int): %d\n", sizeof(int));
printf("sizeof(struct st): %d\n", sizeof(struct st));
On my machine this prints
1
2
4
8
You might think, shouldn't sizeof(struct st)
be 1 + 2 + 4 = 7
? That's certainly a reasonable thought but because of alignment issues there is padding between a
and c
. Therefore, in memory, the struct looks like the following (relative to the first byte of the struct):
0x00000000: char a
0x00000001: padding
0x00000002: first byte of short c
0x00000003: second byte of short c
0x00000004: first byte of int b
0x00000005: second byte of int b
0x00000006: third byte of int b
0x00000007: fourth byte of int b
Consequently (relative to &s1
):
&s1.b - 1 is ((long)&s1.b) - sizeof(int) = 4 - 4 = 0 = &s1
This is why both &s1
and &s1.b - 1
will print the same address. In particular if
&s1 = 0x804a01c
then
&s1.b = 0x804a01c + 0x00000004 = 0x804a020
and
&s1.b - 1 = 0x804a020 - 0x00000004 = 0x804a01c
and
&s1.b - 2 = 0x804a020 - 0x00000008 = 0x804a018
Note, finally, that this is implementation-specific behavior. This is not portable!
Upvotes: 0
Reputation: 96241
Most likely you're printing it wrong:
#include <stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s;
int main(void)
{
printf("s: %p\n", (void *)&s);
printf("s.a: %p\n", (void *)&s.a);
printf("s.b: %p\n", (void *)&s.b);
printf("s.b-1: %p\n", (void *)(&s.b-1));
printf("s.b-2: %p\n", (void *)(&s.b-2));
return 0;
}
Prints for me:
s: 0x100001068
s.a: 0x100001068
s.b: 0x10000106c
s.b-1: 0x100001068
s.b-2: 0x100001064
Things to note:
"%p"
format string. "%p"
needs void *
, and since printf
is a variadic function, I need to cast the arguments to printf
to void *
in this case.What does the above program print for you?
Edit: based upon the actual code posted for printing that you posted later: you are not getting the same value for &s1.b
and &s1.b-1
. You are getting the same value for &s1.b-1
and &s1
. The answer to that is: this happens because of chance. In your case, there is struct padding, and sizeof(short)+sizeof(char)
happens to be ≤ sizeof(int)
. If you were on a machine where any of those assumptions were invalid, you wouldn't see that behavior. I am sure if you changed char
or short
to int
in your code, &s1.b-1
would not equal &s1
, when printed.
Finally, you should cast pointers to void *
before printing:
printf("%p %p \n",(void *)((&s1.b)-1), (void *)&s1);
Upvotes: 2
Reputation: 6678
If the address of s1.b is 0x804a01c, then &s1.b-2 should be 0x804a014 (assuming that int is 4 bytes), not 0x804a018. Perhaps you made a mistake when you reported the address?
Upvotes: 1
Reputation: 279395
There's probably something wrong with your printing code.
#include <stdio.h>
struct st
{
char a;
short c;
int b;
};
struct st s1;
int main() {
printf("%p\n", (void*)(&s1.b));
printf("%p\n", (void*)(&s1.b - 1));
printf("%p\n", (void*)(&s1.b - 2));
}
Output:
0x403024
0x403020
0x40301c
Upvotes: 6