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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2575048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:03:03  来源:igfitidea点击:

Arrow operator (->) usage in C

cpointerssyntax

提问by Mohit Deshpande

I am reading a book called "Teach Yourself C in 21 Days" (I have already learned Java and C# so I am moving at a much faster pace). I was reading the chapter on pointers and the ->(arrow) operatorcame up without explanation. I think that it is used to call members and functions (like the equivalent of the .(dot) operator, but for pointers instead of members). But I am not entirely sure.

我正在阅读一本名为“在 21 天内自学 C”的书(我已经学习了 Java 和 C#,所以我的学习速度要快得多)。我正在阅读有关指针的章节,->(箭头)运算符没有解释就出现了。我认为它用于调用成员和函数(类似于.(点)运算符,但用于指针而不是成员)。但我不完全确定。

Could I please get an explanation and a code sample?

我能得到解释和代码示例吗?

回答by sepp2k

foo->baris equivalent to (*foo).bar, i.e. it gets the member called barfrom the struct that foopoints to.

foo->bar等价于(*foo).bar,即它获取barfoo指向的结构中调用的成员。

回答by Hyman

Yes, that's it.

对,就是那样。

It's just the dot version when you want to access elements of a struct/class that is a pointer instead of a reference.

当您想要访问作为指针而不是引用的结构/类的元素时,它只是点版本。

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;

That's it!

就是这样!

回答by Peter Alexander

a->bis just short for (*a).bin every way (same for functions: a->b()is short for (*a).b()).

a->b(*a).b在各方面都只是缩写(功能相同:a->b()是 的缩写(*a).b())。

回答by Lukasz Matysiak

I'd just add to the answers the "why?".

我只是在答案中添加“为什么?”。

.is standard member access operator that has a higher precedence than *pointer operator.

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

When you are trying to access a struct's internals and you wrote it as *foo.barthen the compiler would think to want a 'bar' element of 'foo' (which is an address in memory) and obviously that mere address does not have any members.

当您尝试访问结构的内部并且您将其编写为*foo.bar这样时,编译器会认为需要 'foo'(这是内存中的地址)的 'bar' 元素,并且显然该地址没有任何成员。

Thus you need to ask the compiler to first dereference whith (*foo)and then access the member element: (*foo).bar, which is a bit clumsy to write so the good folks have come up with a shorthand version: foo->barwhich is sort of member access by pointer operator.

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

回答by Matti Virkkunen

foo->baris only shorthand for (*foo).bar. That's all there is to it.

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

回答by Jayghosh Wankar

struct Node {
    int i;
    int j;
};
struct Node a, *p = &a;

Here the to access the values of iand jwe can use the variable aand the pointer pas follows: a.i, (*p).iand p->iare all the same.

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

Here .is a "Direct Selector" and ->is an "Indirect Selector".

.是一个“直接选择器”和->一个“间接选择器”。

回答by 71GA

Well I have to add something as well. Structure is a bit different than array because array is a pointer and structure is not. So be careful!

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

Lets say I write this useless piece of code:

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

#include <stdio.h>

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

int main(void){

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

}

Here pointer ptrpoints to the address (!) of the structure variable audibut beside address structure also has a chunk of data(!)! The first member of the chunk of datahas the same address than structure itself and you can get it's data by only dereferencing a pointer like this *ptr(no braces).

这里的指针ptr指向结构变量的地址(),audi但在地址结构旁边还有一个数据块)!数据块的第一个成员与结构本身具有相同的地址,您可以通过仅取消引用这样的指针*ptr(无大括号)来获取它的数据。

But If you want to acess any other member than the first one, you have to add a designator like .km, .kph, .kgwhich are nothing more than offsets to the base address of the chunk of data...

但是如果你想访问除第一个成员之外的任何其他成员,你必须添加一个像.km,的指示符.kph.kg它们只不过是数据块基地址的偏移量......

But because of the preceedenceyou can't write *ptr.kgas access operator .is evaluated before dereference operator *and you would get *(ptr.kg)which is not possible as pointer has no members! And compiler knows this and will therefore issue an error e.g.:

但是由于优先级,您不能编写*ptr.kg访问运算符.在取消引用运算符之前进行评估,*并且您会得到*(ptr.kg)这是不可能的,因为指针没有成员!编译器知道这一点,因此会发出错误,例如:

error: ‘ptr' is a pointer; did you mean to use ‘->'?
  printf("%d\n", *ptr.km);

Instead you use this (*ptr).kgand you force compiler to 1stdereference the pointer and enable acess to the chunk of dataand 2ndyou add an offset (designator) to choose the member.

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

Check this image I made:

检查我制作的这张图片:

enter image description here

在此处输入图片说明

But if you would have nested members this syntax would become unreadable and therefore ->was introduced. I think readability is the only justifiable reason for using it as this ptr->kgis much easier to write than (*ptr).kg.

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

Now let us write this differently so that you see the connection more clearly. (*ptr).kg? (*&audi).kg? audi.kg. Here I first used the fact that ptris an "address of audi"i.e. &audiand fact that "reference"&and "dereference"*operators cancel eachother out.

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

回答by prashanth

#include<stdio.h>
struct examp{
int number;
};
struct examp a,*b=&a;`enter code here`
main()
{
a.number=5;
/* a.number,b->number,(*b).number produces same output. b->number is mostly used in linked list*/
   printf("%d \n %d \n %d",a.number,b->number,(*b).number);
}

output is 5 5 5

输出为 5 5 5

回答by Rich Vogt

I had to make a small change to Hyman's program to get it to run. After declaring the struct pointer pvar, point it to the address of var. I found this solution on page 242 of Stephen Kochan's Programming in C.

我不得不对 Hyman 的程序做一个小改动才能让它运行。声明struct指针pvar后,将其指向var的地址。我在 Stephen Kochan's Programming in C 的第 242 页找到了这个解决方案。

#include <stdio.h>

int main()
{
  struct foo
  {
    int x;
    float y;
  };

  struct foo var;
  struct foo* pvar;
  pvar = &var;

  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;
}

Run this in vim with the following command:

使用以下命令在 vim 中运行它:

:!gcc -o var var.c && ./var

Will output:

将输出:

5 - 14.30
6 - 22.40

回答by Gopal Rao

#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;
}