I am currently learning C by reading a good beginner's book called "Teach Yourself C in 21 Days" (I have already learned Java and C# so I am moving at a much faster pace). I was reading the chapter on pointers and the -> (arrow) operator came up without explanation. I think that it is used to call members and functions (like the equivalent of the . (dot) operator, but for pointers instead of members). But I am not entirely sure. Could I please get an explanation and a code sample?
问题:
回答1:
foo->bar
is equivalent to (*foo).bar
, i.e. it gets the member called bar
from the struct that foo
points to.
回答2:
Yes, that's it.
It's just the dot version when you want to access elements of a struct/class that is a pointer instead of a reference.
struct foo { int x; float y; }; struct foo var; struct foo* pvar; var.x = 5; (&var)->y = 14.3; pvar->y = 22.4; (*pvar).x = 6;
That's it!
回答3:
a->b
is just short for (*a).b
in every way (same for functions: a->b()
is short for (*a).b()
).
回答4:
foo->bar
is only shorthand for (*foo).bar
. That's all there is to it.
回答5:
struct Node { int i; int j; }; struct Node a, *p = &a;
Here the to access the values of i
and j
we can use the variable a
and the pointer p
as follows: a.i
, (*p).i
and p->i
are all the same.
Here .
is a "Direct Selector" and ->
is an "Indirect Selector".
回答6:
I had to make a small change to Jack's program to get it to run. After declaring the struct pointer pvar, point it to the address of var. I found this solution on page 242 of Stephen Kochan's Programming in C.
#include int main() { struct foo { int x; float y; }; struct foo var; struct foo* pvar; pvar = &var; var.x = 5; (&var)->y = 14.3; printf("%i - %.02f\n", var.x, (&var)->y); pvar->x = 6; pvar->y = 22.4; printf("%i - %.02f\n", pvar->x, pvar->y); return 0; }
Run this in vim with the following command:
:!gcc -o var var.c && ./var
Will output:
5 - 14.30 6 - 22.40
回答7:
#include int main() { struct foo { int x; float y; } var1; struct foo var; struct foo* pvar; pvar = &var1; /* if pvar = &var; it directly takes values stored in var, and if give new > values like pvar->x = 6; pvar->y = 22.4; it modifies the values of var object..so better to give new reference. */ var.x = 5; (&var)->y = 14.3; printf("%i - %.02f\n", var.x, (&var)->y); pvar->x = 6; pvar->y = 22.4; printf("%i - %.02f\n", pvar->x, pvar->y); return 0; }
回答8:
Dot is a dereference operator and used to connect the structure variable for a particular record of structure. Eg :
struct student { int s.no; Char name []; int age; } s1,s2; main() { s1.name; s2.name; }
In such way we can use a dot operator to access the structure variable
回答9:
The ->
operator makes the code more readable than the *
operator in some situations.
Such as: (quoted from the EDK II project)
typedef EFI_STATUS (EFIAPI *EFI_BLOCK_READ)( IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer ); struct _EFI_BLOCK_IO_PROTOCOL { /// /// The revision to which the block IO interface adheres. All future /// revisions must be backwards compatible. If a future version is not /// back wards compatible, it is not the same GUID. /// UINT64 Revision; /// /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device. /// EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_RESET Reset; EFI_BLOCK_READ ReadBlocks; EFI_BLOCK_WRITE WriteBlocks; EFI_BLOCK_FLUSH FlushBlocks; };
The _EFI_BLOCK_IO_PROTOCOL
struct contains 4 function pointer members.
Suppose you have a variable struct _EFI_BLOCK_IO_PROTOCOL * pStruct
, and you want to use the good old *
operator to call it's member function pointer. You will end up with code like this:
(*pStruct).ReadBlocks(...arguments...)
But with the ->
operator, you can write like this:
pStruct->ReadBlocks(...arguments...)
.
Which looks better?
回答10:
I'd just add to the answers the "why?".
.
is standard member access operator that has a higher precedence than *
pointer operator.
When you are trying to access a struct's internals and you wrote it as *foo.bar
then the compiler would think to want a 'bar' element of 'foo' (which is an address in memory) and obviously that mere address does not have any members.
Thus you need to ask the compiler to first dereference whith (*foo)
and then access the member element: (*foo).bar
, which is a bit clumsy to write so the good folks have come up with a shorthand version: foo->bar
which is sort of member access by pointer operator.