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:
printfand 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.*stuis not an address, it is the firststruct Studentinstu.stuis 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
structtype 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
structargument 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-levelstructargument.But of course
printfdoesn't know what to do with yourstructtype 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 theprintffunction 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. Soprintfprints 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
printfcalls 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
