C中的箭头运算符( - >)用法

Moh*_*nde 245 c syntax pointers

我目前正在通过阅读一本名为"21天自学C"的好初学者的书来学习C(我已经学习了Java和C#,所以我的动作速度要快得多).我正在阅读有关指针的章节,而 - >(箭头)操作符出现时没有解释.我认为它用于调用成员和函数(比如.(点)运算符,但是用于指针而不是成员).但我不完全确定.我可以获得解释和代码示例吗?

sep*_*p2k 435

foo->bar相当于(*foo).bar,即它bar从结构中调用foo指向的成员.

  • 值得注意的是,如果取消引用运算符是后缀,就像在Pascal中那样,根本不需要` - >`运算符,因为它本来相当于更易读的`foo*.bar`.也可以避免使用所有额外括号的整个类型定义函数. (48认同)
  • 不,他只是说* IF * C的创建者会将取消引用运算符作为POSTfix运算符而不是PREfix进行了操作,这会更加容易。但这是C语言中的前缀运算符。 (6认同)
  • @b0fh 没有任何技术原因可以解释为什么语言设计者不能在这种情况下隐式取消引用(Rust 在这种情况下以及其他情况下也这样做),但他们没有。可能是因为他们认为所有取消引用都应该在代码中明确显示和/或因为他们希望保持语言规则尽可能简单。请注意,C++ 智能指针有自己的方法(例如共享指针的 use_count() ),因此有必要区分调用指针上的方法与指针对象上的方法,但这当然不会影响设计的 C. (2认同)

Jac*_*ack 119

对,就是那样.

当您想要访问作为指针而不是引用的struct/class的元素时,它只是点版本.

struct foo
{
  int x;
  float y;
};

struct foo var;
struct foo* pvar;
pvar = malloc(sizeof(pvar));

var.x = 5;
(&var)->y = 14.3;
pvar->y = 22.4;
(*pvar).x = 6;
Run Code Online (Sandbox Code Playgroud)

而已!

  • 不应该是: pvar = malloc(sizeof(struct foo)) 或 malloc(sizeof(*pvar)) 吗? (5认同)
  • 由于pvar未初始化,如果你想让pvar指向一个新的结构,那么你将如何初始化它,而不是`pvar =&var`? (3认同)

Pet*_*der 31

a->b只是对于短(*a).b以各种方式(同为功能:a->b()是短期的(*a).b()).


Luk*_*iak 24

我只是在答案中加上"为什么?".

.是标准成员访问运算符,其优先级高于*指针运算符.

当你试图访问struct的内部并且你编写它时,*foo.bar编译器会认为想要一个'bar'元素'foo'(这是一个内存中的地址),显然这个地址没有任何成员.

因此,你需要让编译器首先取消引用whith (*foo),然后访问成员元素:(*foo).bar这有点笨拙,所以好人们想出了一个速记版本:foo->bar这是指针运算符的一种成员访问.


Mat*_*nen 19

foo->bar只是简写(*foo).bar.这里的所有都是它的.


小智 10

struct Node {
    int i;
    int j;
};
struct Node a, *p = &a;
Run Code Online (Sandbox Code Playgroud)

这里访问的价值观ij我们可以使用变量a和指针p如下:a.i,(*p).i并且p->i都是一样的.

.是一个"直接选择器",->是一个"间接选择器".


71G*_*1GA 8

好吧,我也必须添加一些东西。结构与数组有点不同,因为数组是指针而结构不是。所以要小心!

假设我写了这段无用的代码:

#include <stdio.h>

typedef struct{
        int km;
        int kph;
        int kg;
    } car;

int main(void){

    car audi = {12000, 230, 760};
    car *ptr = &audi;

}
Run Code Online (Sandbox Code Playgroud)

这里的指针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);
Run Code Online (Sandbox Code Playgroud)

相反,您使用它(*ptr).kg并强制编译器第一次取消引用指针并启用对数据块的访问,第二次添加偏移量(指示符)以选择成员。

检查我制作的这张图片:

在此处输入图片说明

但是如果你有嵌套成员,这种语法将变得不可读,因此->被引入。我认为可读性是使用它的唯一正当理由,因为它ptr->kg(*ptr).kg.

现在让我们换一种方式来写,以便您更清楚地看到这种联系。(*ptr).kg? (*&audi).kg? audi.kg. 在这里,我第一次使用的事实,ptr是一个“地址audi,即&audi与事实“引用” &“解引用” *运营商取消了海誓山盟。