0

Q1: I'm trying to understand why in this code I'm supposed to use a dot operator when calling the string pointer rather than an arrow which is used for pointers.

Q2: If I was trying to initialize age would I use the dot operator?

typedef struct Person 
{
  char *name;
  int age;

} Person;

Person* deletePerson(Person *person, int totalPeople) 
{
     int i;

     for(i=0; i<totalPeople; i++) 
     {
     free(person[i].name); 
     free(person); 
     }

     return NULL;
}
Neo
  • 47
  • 6

4 Answers4

4

You need to use the arrow -> operator when you have a pointer to a struct (or union) on the left, and the dot . operator when you have a struct on the left. It doesn't depend on what's on the right.

If person was a pointer to a single Person, to access its field, you'd use person->name and person->age.

But here person is evidently a pointer to the first element of an array of Person. (A pointer to the first element is how arrays are passed around in C.) To access an individual element of the array, you use the subscript operator (square brackets […]): person[i]. person[i] is the element with index i, not a pointer to the element with index i. Since person[i] is a struct, you use the dot operator to access its fields.


In addition, as others have already remarked, free(person); inside the loop doesn't make sense. You'd free the whole array as soon as you've processed the first element. Call free(person) after the loop, once you've finished cleaning up all the elements of the array (assuming that person was allocated with malloc).

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
1

person->name would be synonymous with person[0].name; since you want to refer to the name of an arbitrary person, you couldn't use -> this way.

(I suppose you would use (person+i)->name, but your original code is clearer, IMHO.)

As for initializing age: what else would you use other than .?

P.S. freeing person inside the loop means a) you free it multiple times, and b) person[i] will be a problem after the first iteration.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
0

For starters the function is invalid and has a bug.

I think you mean

Person* deletePerson(Person *person, int totalPeople) 
{
     for ( int i=0; i < totalPeople; i++ ) 
     {
         free( person[i].name ); 
         free( person[i] ); 
     }

     free( person );

     return NULL;
}

This statement

free(person[i].name);

can be equivalently rewriten like

free( ( person + i )->name );

or even like

free( ( *( person + i ) ).name );

However the first statement is more readable.

According to the C Standard (6.5.2.1 Array subscripting)

2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

In C, the -> operator is a cosmetic substitute for (*var).field, and the [ ] is a substitute for *(ptr + n).

In your code, the line:

free(person[i].name);

Is equivalent to:

free((*(person + i)).name)

If you use -> instead of the dot operator that would be wrong. I can see why you are confused, to make it look simpler, the function parameter “Person *person” is basically an array of struct Person, equivalent to “Person person[]”. If you were to access only the first Person in the array you could have used person->name which is the same as person[0].name

Tal Avraham
  • 300
  • 1
  • 6