简体   繁体   中英

How do I define struct pointers and non-pointers (. and ->)?

If my struct looks like:

struct contact {
    char* name;
    int number;
};

and one of the functions I'm writing looks like:

int find(struct contact* pb, int len, char* name)
{
    for (int i = 0; i < len; i++)
        if (strcmp(name, pb->name[i]) == 0) // pb[i].name is OK!
            return pb[i].number; // pb->number[i] ? - but number is not a pointer
.
.
.

If we will take a closer look at the function find , we can see that the following: pb->name[i] is like writing pb[i].name is the same. But what about: pb[i].number ? I know that number is not a pointer, so how can I write it similair to: pb[i].number ? It can not be: pb->number[i] , right?

pb->name[i] is not the same as pb[i].name .

pb->name[i] tells the computer to:

  • Look at the value stored in the variable pb (which is an address)
  • Look at the struct which that address points to ( -> )
  • Look at the name in that struct.
  • Look at the i -th thing in the array which name points to.

ie it returns the i -th character in the first contact's name.

pb[i].name tells the computer to:

  • Look at the value stored in the variable pb (which is an address)
  • Look at the i -th struct in the array which that address points to
  • Look at the name in that struct.

ie it returns the address of the i -th contact's name.

pb->number[i] makes no sense because number isn't an array. You're asking for the i -th thing from the first contact's number, but the number isn't an array or a pointer to one.

pb->name[i] is also wrong but it makes sense. You're asking the computer for something which isn't the thing you want, but at least it's a thing which is possible, so the computer does it anyway.

The array subscript operation a[i] is exactly equivalent to *(a + i) - given a starting address a , compute the address of the i 'th object following that address and dereference the result.

This means that the expression *pb is equivalent to *(pb + 0) , which is equivalent to pb[0] . The subscript operation implicitly dereferences pb , so the type of the expression pb[i] is struct contact .

You use the . operator when the operand is a struct or union type, and the -> operator when the operand is a pointer to a struct or union type.

Since the expression pb[i] has type struct contact , you'd use the . operator to access both the name and number members:

if ( !strcmp( name, pb[i].name ) ) 
  return pb[i].number;

pb->name[i] is not the same as pb[i].name , and as used in your code will lead to a runtime error. You're not referencing the i 'th name in your pb array - instead, you're referencing the i 'th character in the name member of pb[0] . You're passing that character value to strcmp , which expects an address value of type char * . It's very unlikely that any regular character value is also a valid address, so you will almost certainly see a runtime error there.

In order to directly answer this question I would suggest to use (*pb).number

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM