C语言中,指向变量的指针和指向结构体的指针有何不同?

6
在学习C语言时,我刚开始研究结构体指针,并有一些问题。假设我创建了一个名为“myStructure”的结构体,然后创建了一个指向“myStructure”的指针“myStructurePointer”。那么,“*myStructurePointer”和“myStructure”是引用同一事物的两种方式吗?如果是,为什么需要“->”运算符?使用“*myStructurePointer.variable_name”似乎比“myStructurePointer->variable_name”更简单易懂。

更准确地说,myStructure(*myStructurePointer) 是引用同一事物的两种方式。 - bta
6个回答

8

您说得对,

(*structurePointer).field

与...完全相同

structurePointer->field

你拥有的是:

*structurePointer.field

如果试图在指针变量上使用.运算符,然后取消引用该结果-它甚至不会编译。如果您希望表达式等效,请按照我在上面第一个示例中的方式使用括号。在这种简单情况下,箭头至少可以节省几个按键。

如果结构字段具有指针类型,可能指向另一个结构,则使用->可能更有意义:

structurePointer->field->field2

对比。

(*(*structurePointer).field).field2

是的,我花了一段时间才弄明白那个。就我个人而言,我喜欢“->”语法,因为它让我想起了Perl。 - amphetamachine

5
*myStructurePointer.variable_name的问题在于*的优先级低于.,因此它将被解释为*(myStructurePointer.variable_name)。相当于myStructurePointer->variable_name的是(*myStructurePointer).variable_name,其中需要使用括号。 a->b(*a).b之间没有区别,但->更易于使用,特别是在存在嵌套结构的情况下。(*(*(*a).b).c).d比`a->b->c->d`难以阅读。

4

总的来说,学习C运算符优先级:

这里"."运算符在"*"之前处理 -> 因此需要使用括号。


1
你可以通过大量使用括号来强制处理 *. 之前,但是 -> 符号被创建为一种更易于阅读的替代方法。 - bta
@Michael,我认为OP真正想问的是(*p).fp->f之间的区别。缺少的()是由于经验不足,我想。 - Carl Norum
我的回答在你的下面添加后更有意义,@Carl :-) - Michael Mullany
抱歉,卡尔。在多个有用的答案之间选择确实很困难。我选择了迈克的答案,因为它更全面地解决了我的困惑;我刚接触C语言,并且只能从Java中直接翻译出先例,所以迈克尔提供的链接非常有帮助;不过,你们两个似乎都认为迈克应该得到荣誉,所以我会采纳他的答案。 - objectivesea
没什么大不了的,我只是觉得自己误解了问题。 - Carl Norum

1

丹尼斯·里奇曾经指出,deref 应该是一个后缀运算符1

没错,以下两种写法是等价的:

pointer->field
(*pointer).field
pointer[0].field

如果间接运算符采用后缀语法,C语言将会有所不同,但在这种情况下,它根本不需要使用“->”符号。
想象一下,在那个平行宇宙中,常见的C语言习惯用法会是什么样子,这真是很有趣...
do s1++* = c = s2++*;
   while(c);

while(n-- > 0)
    s++* = '\0';

p*.x = 1;
p*.y = 2;
. . .
. . .
. . .

1. 查看C语言的发展历程。, 丹尼斯·里奇


0

使用 * 解引用指针,这样你就可以使用点语法来访问字段。如果你不解引用指针,则使用 -> 来访问字段。你可以使用任何一种方式。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接