在结构体中使用点运算符和箭头运算符以及字符串指针

时间:2019-09-06 17:56:12

标签: c

Q1:我试图理解为什么在这段代码中,我在调用字符串指针时使用点运算符,而不是使用用于指针的箭头。

Q2:如果我尝试初始化年龄,我会使用点运算符吗?

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;
}

4 个答案:

答案 0 :(得分:4)

当您在左侧指向结构(或联合)的指针时,您需要使用箭头->运算符;当您指向一个结构体(或联合)的指针时,需要使用点.左侧的结构。它不取决于右边的内容。

如果person是指向单个Person的指针,则要访问其字段,则可以使用person->nameperson->age

但是这里person显然是指向Person数组的第一个元素的指针。 (指向第一个元素的指针是如何在C中传递数组。)要访问数组的单个元素,请使用下标运算符(方括号[…]):person[i]person[i]是索引为i的元素,而不是指向索引为i的元素的指针。由于person[i]是一个结构,因此您可以使用点运算符来访问其字段。


此外,正如其他人已经提到的那样,循环内的free(person);毫无意义。处理完第一个元素后,就可以释放整个数组。清理完数组的所有元素后,请在循环后调用free(person)(假设person已分配给malloc)。

答案 1 :(得分:1)

person->name将与person[0].name同义;由于您要引用任意person的名称,因此无法使用->

(我想您会使用(person+i)->name,但是您的原始代码更清晰,恕我直言。)

关于初始化age:除了.以外,您还会使用什么?

P.S。在循环中free person意味着a)您多次释放它,并且b)person[i]将在第一次迭代后出现问题。

答案 2 :(得分:0)

对于初学者来说,该功能无效且存在错误。

我想你是说

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

     free( person );

     return NULL;
}

此声明

free(person[i].name);

可以等效地重写

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

甚至喜欢

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

但是第一条语句更具可读性。

根据C标准(6.5.2.1数组下标)

  

2后缀表达式,后跟方括号[]   是数组对象元素的下标名称。的   下标运算符[]的定义是 E1 [E2]相同   到(*((E1)+(E2)))。由于适用于   二进制+运算符,如果E1是数组对象(相当于一个指针)   到数组对象的初始元素),并且E2是整数,   E1 [E2]表示E1的第E2个元素(从零开始计数)。

答案 3 :(得分:0)

在C中,->运算符是(* var).field的替代品, 并且[]代替*(ptr + n)。

在您的代码中,该行:

free(person[i].name);

等效于:

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

如果使用->代替点运算符,那将是错误的。 我可以看到为什么感到困惑,为了使其看起来更简单,函数参数“ Person * person”基本上是struct Person的数组,等效于“ Person person []”。 如果仅访问数组中的第一个Person,则可以使用person-> name,该名称与person [0] .name

相同