1

I have simple the nested structure:

struct abc {
        int i;
};

struct milan {
        struct abc obj;
};

int main()
{
    struct milan *ptr; 
    ptr = malloc(sizeof(struct milan)); 
    ptr->obj.i = 10;    
    printf("%d\n", ptr->obj); 
} 

It prints 10, but how the de-reference a pointer taking place here, is ptr->obj the same as &->obj == *obj ?

sj95126
  • 6,520
  • 2
  • 15
  • 34
Milan
  • 1,447
  • 5
  • 19
  • 27
  • 1
    `ptr->obj` is the same as `(*ptr).obj`. Does that answer your question? – Thomas Aug 05 '22 at 09:08
  • 7
    The seemingly random keystrokes of `&->obj == *obj` notwithstanding, is you real question how `10` is being emitted, since you never actually sent `ptr->obj.i` to `printf` ? First, you're lying to `printf`. You're telling it you're sending an `int` and instead you sent a `abc`. However, in this case, an `abc` happens to have an `int` as its first and only member. Add a member on either side of that `i` and watch the fireworks. Then stop doing all of the above. – WhozCraig Aug 05 '22 at 09:10
  • 2
    The statement `printf("%d\n", ptr->obj);` exhibits undefined behaviour. If you turn your compiler warning level up (`-Wall` on `gcc` or `clang`) you should get a diagnostic message along the lines of `warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct abc’ [-Wformat=]` . – G.M. Aug 05 '22 at 09:16
  • 1
    And fwiw, the whole dynamic allocation and `milan` are irrelevant here, add confusion to the issue, and are thus a red herring. You could just as easily have ill-advisedly done `struct abc obj; obj.i=10; printf("%d\n", obj);`. Turn up your warnings and treat them as errors (because that's exactly what they are). – WhozCraig Aug 05 '22 at 09:17
  • 2
    _"is `ptr->obj` same as `&->obj == *obj`"_. No, it's not the same. `ptr->obj` is the same as `(*ptr).obj`, and `&->obj == *obj` is totally meaningless. – Jabberwocky Aug 05 '22 at 09:17
  • You probably want `printf("%d\n", ptr->obj.i)` instead of `printf("%d\n", ptr->obj)`, latter being undefined behaviour. – Jabberwocky Aug 05 '22 at 09:23
  • Try `printf( "%d\n", *p );` and the program will again print "10"... Mysterious... (Do NOT do this in real life...) – Fe2O3 Aug 05 '22 at 09:28
  • 1
    @Fe2O3, no it's not mysterious, it's undefined behavior. – Jabberwocky Aug 05 '22 at 09:29
  • 1
    @Jabberwocky Definitely a no-no! However, it is 'experiments' like this that teach that `obj` is 0 bytes offset from the start of the memory block, as is `obj.i`... It's how one develops the mental imagery to understand more complex ideas... Cheers! – Fe2O3 Aug 05 '22 at 09:39
  • 2
    @Fe2O3 "Undefined behavior" is a technical term that describes what we have here. The standard does not _define_ how an implementation _behaves_. So, if you write `obj`, which is clearly of type `struct abc`, and interpret it as `int`, it only "works" if the specific compiler inserted no padding and the offset of `i` in `obj` is 0. If it "works" with one compiler, it does not need to work with another compiler. – the busybee Aug 05 '22 at 09:46
  • Fe203, Yeah I see, ptr is pointing to a memory block that is start of both struct milan and struct abc. I am just confused how ptr->ob is same as (*ptr).obj? – Milan Aug 05 '22 at 09:47
  • `a->b` is just shorthand for `(*a).b`. It makes code more readable. – Jabberwocky Aug 05 '22 at 09:51
  • @Jabberwocky, in my head, I am just thinking if this (*a).b , still breakdown further, something like (*a) is de-referencing the address pointed by a which is struct abc and then .b mean accessing offset at byte 0, but not sure this make sense to you ? – Milan Aug 05 '22 at 10:03
  • 1
    @Milan I think you should get a good C book for starters. – Jabberwocky Aug 05 '22 at 10:04
  • 1
    `ptr->obj` is the same as `(*ptr).obj` because that's the definition of the `->` operator. It makes things like `a->b->c` possible, which is far more readable than `(*(*a).b).c)` – William Pursell Aug 05 '22 at 10:23

1 Answers1

2

The expression ptr->obj is the same as ( *ptr ).obj.

From the C Standard (6.5.2.3 Structure and union members)

4 A postfix expression followed by the -> operator and an identifier designates a member of a structure or union object. The value is that of the named member of the object to which the first expression points, and is an lvalue.96) If the first expression is a pointer to a qualified type, the result has the so-qualified version of the type of the designated member

and

3 A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member,95) and is an lvalue if the first expression is an lvalue. If the first expression has qualified type, the result has the so-qualified version of the type of the designated member.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Vlad, does it mean -> is de-reference operator , and it would de-reference anything that it points to, in this case , it is de-referencing what is at address "struct abc", right ? – Milan Aug 05 '22 at 09:42
  • 1
    @Milan It is not a dereference operator because it does not dereference the pointed object. It is a member access operator by means of a pointer. The dereference operator is the unary operator *. – Vlad from Moscow Aug 05 '22 at 09:48
  • @Milan There is no need to introduce your own terms. Use the terms defined in the C Standard. – Vlad from Moscow Aug 05 '22 at 09:55
  • 1
    @Milan Under the hood as I pointer out the operator ptr->obj can be evaluated like ( *ptr ).obj. That is the left side pointer can be dereferenced. – Vlad from Moscow Aug 05 '22 at 10:03