Home > database >  why pointer of an array of structure printing different addresses
why pointer of an array of structure printing different addresses

Time:07-16

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));

}
  1. why (*(stu 1)) printing different addresses in (a) and (b)?
  2. 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:

  1. 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.

  2. *stu is not an address, it is the first struct Student in stu. 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.

  3. So per the second point, when you do *stu, you get the first struct Student. When you do *(stu 1), you get the second struct 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?

  4. Well, how is a struct type passed to printf?

    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-level struct argument.

  5. But of course printf doesn't know what to do with your struct type argument - your compiler knows, because it sees the call to printf, that it needs to do this copy-to-stack-and-pass-the-address-of-copy trick - but the printf 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. So printf prints that internal implicit incidental copy's address.

  6. 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

  • Related