我正在读一本叫做《21天自学C语言》的书(我已经学会了Java和c#,所以我正在以更快的速度前进)。我正在阅读关于指针的章节,->(箭头)操作符没有解释就出现了。我认为它是用来调用成员和函数的(类似于。(点)操作符,但用于指针而不是成员)。但我不完全确定。
我能得到一个解释和一个代码样本吗?
我正在读一本叫做《21天自学C语言》的书(我已经学会了Java和c#,所以我正在以更快的速度前进)。我正在阅读关于指针的章节,->(箭头)操作符没有解释就出现了。我认为它是用来调用成员和函数的(类似于。(点)操作符,但用于指针而不是成员)。但我不完全确定。
我能得到一个解释和一个代码样本吗?
当前回答
我还得补充点什么。结构与数组有点不同,因为数组是指针,而结构不是。所以要小心!
假设我写了这段无用的代码:
#include <stdio.h>
typedef struct{
int km;
int kph;
int kg;
} car;
int main(void){
car audi = {12000, 230, 760};
car *ptr = &audi;
}
这里的指针ptr指向结构变量audi的地址(!),但在地址结构旁边也有一大块数据(!)!数据块的第一个成员具有与结构本身相同的地址,您可以通过对*ptr(不带大括号)这样的指针进行解引用来获得它的数据。
但是如果你想访问除第一个成员之外的任何其他成员,你必须添加一个指示符,如.km, .kph, .kg,这只不过是对数据块的基址的偏移量…
但是因为优先级,你不能写*ptr。Kg作为访问操作员。在解引用操作符*之前求值,您将得到*(ptr.kg),这是不可能的,因为指针没有成员!编译器知道这一点,因此会发出一个错误,例如:
error: ‘ptr’ is a pointer; did you mean to use ‘->’?
printf("%d\n", *ptr.km);
相反,您可以使用this (*ptr)。Kg和你强迫编译器首先解引用指针,并允许访问数据块和第二你添加一个偏移量(指示符)选择成员。
看看我做的这张图:
但是如果你有嵌套的成员,这个语法将变得不可读,因此->被引入。我认为可读性是使用它的唯一合理的原因,因为这个ptr->kg比(*ptr).kg更容易编写。
现在让我们用不同的方式来写,这样你就能更清楚地看到其中的联系。(* ptr)。Kg⟹(*&奥迪)。Kg⟹audi.kg。这里我首先使用了ptr是“audi的地址”,即&audi,以及“引用”&和“解引用”*操作符相互抵消的事实。
其他回答
我只想在答案中加上一个“为什么”。
. 标准成员访问操作符,其优先级高于*指针操作符。
当你试图访问一个结构的内部,你把它写成*foo。Bar然后编译器会认为需要一个'foo'(内存中的地址)的' Bar '元素,显然这个地址没有任何成员。
因此,你需要要求编译器先对(*foo)解引用,然后访问成员元素:(*foo)。Bar,写起来有点笨拙,所以好事者想出了一个简写版本:foo-> Bar,这是一种指针操作符的成员访问。
struct Node {
int i;
int j;
};
struct Node a, *p = &a;
在这里要访问i和j的值,我们可以使用变量a和指针p,如下所示:a.i, (*p)。I和p-> I都是一样的。
在这里。是“直接选择器”,->是“间接选择器”。
Foo ->bar只是(* Foo).bar的简写。这就是它的全部。
#include<stdio.h>
int main()
{
struct foo
{
int x;
float y;
} var1;
struct foo var;
struct foo* pvar;
pvar = &var1;
/* if pvar = &var; it directly
takes values stored in var, and if give
new > values like pvar->x = 6; pvar->y = 22.4;
it modifies the values of var
object..so better to give new reference. */
var.x = 5;
(&var)->y = 14.3;
printf("%i - %.02f\n", var.x, (&var)->y);
pvar->x = 6;
pvar->y = 22.4;
printf("%i - %.02f\n", pvar->x, pvar->y);
return 0;
}
Foo ->bar等价于(* Foo)。Bar,即它从foo指向的结构体中获取名为Bar的成员。