Well I have to add something as well. Structure is a bit different than array because array is a pointer and structure is not. So be careful!
Lets say I write this useless piece of code:
#include <stdio.h>
typedef struct{
int km;
int kph;
int kg;
} car;
int main(void){
car audi = {12000, 230, 760};
car *ptr = &audi;
}
Here pointer ptr
points to the address (!) of the structure variable audi
but beside address structure also has a chunk of data (!)! The first member of the chunk of data has the same address than structure itself and you can get it's data by only dereferencing a pointer like this *ptr
(no braces).
But If you want to acess any other member than the first one, you have to add a designator like .km
, .kph
, .kg
which are nothing more than offsets to the base address of the chunk of data...
But because of the preceedence you can't write *ptr.kg
as access operator .
is evaluated before dereference operator *
and you would get *(ptr.kg)
which is not possible as pointer has no members! And compiler knows this and will therefore issue an error e.g.:
error: ‘ptr’ is a pointer; did you mean to use ‘->’?
printf("%d\n", *ptr.km);
Instead you use this (*ptr).kg
and you force compiler to 1st dereference the pointer and enable acess to the chunk of data and 2nd you add an offset (designator) to choose the member.
Check this image I made:
But if you would have nested members this syntax would become unreadable and therefore ->
was introduced. I think readability is the only justifiable reason for using it as this ptr->kg
is much easier to write than (*ptr).kg
.
Now let us write this differently so that you see the connection more clearly. (*ptr).kg
⟹ (*&audi).kg
⟹ audi.kg
. Here I first used the fact that ptr
is an "address of audi
" i.e. &audi
and fact that "reference" &
and "dereference" *
operators cancel eachother out.