1
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
14
  • 3
    (1) This can't be your actual code (missing a { in the structure definition). (2) *stu is not an address of a structure ... it is a structure. Commented Jul 16, 2022 at 7:14
  • 1
    Can't reproduce: this isn't your actual code. You are using the wrong format spec for a pointer anyway, so the result is undefined. Commented Jul 16, 2022 at 7:14
  • 2
    (3) As soon as you pass the wrong type of argument to printf for the given format specifier(s), then you have undefined behaviour. After that, all bets are off. And there is no format specifier that expects a struct Student as its corresponding argument. Commented Jul 16, 2022 at 7:17
  • 1
    This codes outputs at (a) 10 from *(stu) and at (b) 15 from *(stu+1) the first data of each element, not addresses. Commented Jul 16, 2022 at 7:19
  • 1
    @Rahul subject to certain things. When passing an array to a function it automatically decays to a pointer to its first element. Commented Jul 16, 2022 at 7:25

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.