struct Student{
int roll;
char name[8];
float marks;
};
void main(){
struct Student stu[5] = {{10,"xyz",30},{15,"abc",50},{20,"lmn",70}};
printf("%d \n", (*stu).roll);
printf("%d \n", (*(stu 1)).roll);
printf("%x %x\n", (*stu), (*(stu 1))); // <- here (a)
printf("%x \n", (*(stu 1))); // <-here (b)
printf("%x \n", (stu));
printf("%x \n", (stu 1));
}
- why (*(stu 1)) printing different addresses in (a) and (b)?
- why address of (*(stu 1)) in (b) and address of (*stu) same ?
// --------------------
here is output i am getting
10
15
351ff8c0 351ff8b0
351ff8c0
351ff8d0
351ff8e0
CodePudding user response:
Because those printf
calls aren't printing the addresses of stu
elements, they're printing the addresses of struct Student
copies which have been made on the call stack for argument-passing.
Here's why:
printf
and the"%x"
format do not tell the language to take the address of their argument. They just take whatever they got, and interpret it as an integer, and print that integer as hex.*stu
is not an address, it is the firststruct Student
instu
.stu
is an array, which for most purposes is an address, and*
goes the other way: it gets the value at an address, not the address of a thing.So per the second point, when you do
*stu
, you get the firststruct Student
. When you do*(stu 1)
, you get the secondstruct Student
.But per the first point, you aren't getting their addresses, you're just getting the structs themselves, and passing those structs - all their contents to
printf
.So why do they still look like addresses?
Well, how is a
struct
type passed toprintf
?Turns out there are multiple possible ways, and the exact way depends on your computer, operating system, and compiler.
One way, the way your system seems to be doing, is to make a new copy of each
struct
argument onto the stack, and then pass the address of that copy to the function as the "actual" machine-level argument. Then the function, which is presumed to know what to do with that argument of that type, is expected to be compiled to look through that address to get the "actual" C-levelstruct
argument.But of course
printf
doesn't know what to do with yourstruct
type argument - your compiler knows, because it sees the call toprintf
, that it needs to do this copy-to-stack-and-pass-the-address-of-copy trick - but theprintf
function doesn't know that its machine-level argument is actually an internal address argument, it just knows that you told it (by writing "%x") that this argument is an integer. Soprintf
prints that internal implicit incidental copy's address.So why are the addresses between calls different?
Because each call gets new copies, but the stack space is reused, and nothing changes the stack layout between the two calls, so the first argument to both
printf
calls gets the same address, then if there's a second argument it gets an adjacent address, and so on.So
printf("%x %x\n", *stu, *(stu 1))
gives the first address to the copy of*stu
, and the second address to the copy of*(stu 1)
.But
printf("%x\n", *(stu 1))
gives the first address to its copy of*(stu 1)
.
(Notice also that the addresses from those two printf
lines in your example are different by the same small amount from the addresses in the next two printf
lines. This is because the next two lines are correctly getting the addresses of elements in stu
like you wanted, and stu
is also allocated on the stack, as is typical for function-scoped variables. This was a big clue for me in figuring out what's happening.)
CodePudding user response:
The printf()
functions aren't printing the actual addresses of the structure rather the copies of struct student
which have been made on the call stack to service the printf()
function
So, the line
printf("%x %x\n", (*stu), (*(stu 1)));
Simply prints the first 2 created addresses on the stack.
To better illustrate if we consider the statement
printf("%x %x\n", (*(stu 5)), (*(stu 4)));
printf("%x %x\n", (*(stu 3)), (*(stu 2)));
These two should print the same addresses as they are simply the first 2 copies created on the stack to service the printf()
function
The output I got was
225ffae0 225ffad0
225ffae0 225ffad0