C中的“指针-> register_next->值”是否与“指针-> register_next.value”相同?

时间:2019-02-23 22:49:50

标签: c pointers search

我正在研究列表(C语言)中的搜索过程,并且发现过程在编写条件时同时使用箭头点运算符。 / p>

对于像这样的结构 ...

ID#   Name   Date   Comment
1     xxx    xxx    xxx  
2     yyy    yyy    yyy

我见过...

struct node{
  int value; //value, can be any type
  struct node *next;
};

...和

if(current->next->value == searched_value)

...正在使用。我的问题是:在任何给定的情况下这些方法都可以互换吗?(即它们是相同的)

3 个答案:

答案 0 :(得分:1)

不。它们肯定是不一样的,并且不能互换。

箭头运算符->仅在将结构的指针作为变量时才有效。

所以:

struct *p;
p->a = 0; // correct
p.a = 0; //syntax error

很显然,您一定在寻找其他东西,因为如果nextstruct node *类型(指向struct node的指针),那么current->next.value就是错误。

gcc中,您会收到一条错误消息:error: request for member ‘value’ in something not a structure or union

答案 1 :(得分:1)

current->next->value也可以写成(*(*current).next).value)

需要这些括号的原因是.的优先级高于*->基本上只是语法糖,可以减少括号的数量。

  

在任何给定情况下这些方法都可以互换吗?

以某种方式。如果正确使用括号,则始终可以使用点而不是箭头。您也可以采用其他方式。这段代码编译时没有警告,并显示1 2 3 4

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  int foo; 
  int bar;
} myStruct;

int main() {
    myStruct a;
    (&a)->foo = 1;
    a.bar = 2;

    myStruct * b = malloc(sizeof *b);
    b->foo = 3;
    (*b).bar = 4;

    printf("%d %d %d %d\n", a.foo, (&a)->bar, (*b).foo, b->bar);
}

->要求左运算符是指针,而.要求它不是指针。但是如您所见,对指针进行解引用(使用*)会为您提供指针所指向的数据,因此您可以改用.。并且使用&为您提供对象的地址,这将强制使用->而不是.

在实践中,这绝对不是问题。选择最方便的方法,我想不出一个我不知道该选择哪个示例。

实际上,这与[]运算符有关,该运算符用于索引数组。那也只是语法糖。表达式a[i]等效于*(a+i)。有趣的是,a[i]实际上与i[a]相同。

答案 2 :(得分:1)

正如@PabloSantaCruz正确指出的那样,使用'->''.'访问结构的成员非常不同。

要知道要使用哪个,只需回答以下问题:“我是否有结构或指向结构的指针?”

访问结构成员时,'->'(箭头)运算符用于取消引用指向结构的指针以访问成员。在处理结构本身时,'.'(点)运算符用于访问其成员。

没有什么比实践更好的了,还有一个示例可以帮助比较/对比用法,例如,以下内容声明了一个结构数组作为您的列表,其中每个元素都是一个结构。要简单地访问每个元素的成员,只需要点运算符即可。但是,为了显示它们之间的关系,如果您获取每个元素的地址,从而创建一个指向它的指针,则可以使用箭头运算符。

#include <stdio.h>

struct node {
    int val;
    struct node *next;
};

int main (void) {

    struct node list[2] = {{1, &list[1]}, {2, NULL}},   /* array */
                *l = list;  /* pointer to first element */

    puts ("\nusing list, e.g. list[0].val\n");      /* the dot operator */
    printf (" %d %d\n", list[0].val, list[1].val);

    /* taking the address of each element and using the arrow operator */
    puts ("\nusing address of each list element, e.g. (&list[0])->val\n");
    printf (" %d %d\n", (&list[0])->val, (&list[1])->val);

    puts ("\nusing l, e.g. l->val\n");  /* using the pointer & arrow op. */
    printf (" %d %d\n", l->val, (l + 1)->val);

    puts ("\ntraversing list using l\n"); /* traversing with the pointer */
    while (l) {
        printf (" %d", l->val);
        l = l->next;
    }
    putchar ('\n');
}

在上述每种情况下,您只需回答问题“我是否有结构或指向该结构的指针?” 即可知道要使用哪个运算符。

使用/输出示例

$ ./bin/ll_array

using list, e.g. list[0].val

 1 2

using address of each list element, e.g. (&list[0])->val

 1 2

using l, e.g. l->val

 1 2

traversing list using l

 1 2

仔细检查一下,如果还有其他问题,请告诉我。