我正在研究列表(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)
...正在使用。我的问题是:在任何给定的情况下这些方法都可以互换吗?(即它们是相同的)
答案 0 :(得分:1)
不。它们肯定是不一样的,并且不能互换。
箭头运算符->
仅在将结构的指针作为变量时才有效。
所以:
struct *p;
p->a = 0; // correct
p.a = 0; //syntax error
很显然,您一定在寻找其他东西,因为如果next
是struct 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
仔细检查一下,如果还有其他问题,请告诉我。