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

时间:2010-04-04 16:21:12

标签: c pointers syntax

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

12 个答案:

答案 0 :(得分:402)

foo->bar相当于(*foo).bar,即它从bar指向的结构中获取名为foo的成员。

答案 1 :(得分:114)

是的,就是这样。

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

struct foo
{
  int x;     // 5
  float y;
};

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

var.x = 5;   // var.x is 5
(&var)->y = 14.3;
pvar->y = 22.4;
(*pvar).x = 6;   // (*pvar).x is 5

就是这样!

答案 2 :(得分:29)

a->b只是(*a).b的缩写(功能相同:a->b()(*a).b()的缩写。)

答案 3 :(得分:20)

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

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

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

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

答案 4 :(得分:19)

foo->bar只是(*foo).bar的简写。这就是它的全部内容。

答案 5 :(得分:10)

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

在这里,为了访问ij的值,我们可以使用变量a和指针p,如下所示:a.i,{{ 1}}和(*p).i都是一样的。

此处p->i是"直接选择器" .是"间接选择器"。

答案 6 :(得分:4)

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

可以说我写了这段无用的代码:

#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之类的指示符,它们仅是基数的偏移量数据块 ...

的地址

但是由于preceedence,您不能写*ptr.kg,因为访问操作符.在取消引用操作符*之前被求值,您将得到*(ptr.kg)由于指针没有成员,因此不可能!并且编译器知道这一点,因此将发出错误,例如:

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

相反,您使用此(*ptr).kg并强制编译器 1st 取消引用指针并启用对数据块 2nd 的访问权限strong>您添加一个偏移量(标识符)以选择成员。

检查我制作的这张图片:

enter image description here

但是,如果您有嵌套成员,则该语法将变得不可读,因此引入了->。我认为可读性是使用它的唯一正当理由,因为此ptr->kg(*ptr).kg更容易编写。

现在,让我们以不同的方式写这个,以便您更清楚地看到连接。 (*ptr).kg(*&audi).kgaudi.kg。在这里,我首先使用ptraudi的地址(即&audi)和“ reference” { {1}}和“ dereference” &运算符将彼此抵消。

答案 7 :(得分:1)

我必须对杰克的程序进行一些小改动才能让它运行起来。声明结构指针pvar后,将其指向var的地址。我在Stephen Kochan的C编程中找到了这个解决方案。

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

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

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

将输出:

5 - 14.30
6 - 22.40

答案 8 :(得分:1)

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

答案 9 :(得分:1)

在某些情况下,->运算符使代码比*运算符更具可读性。

例如:(引自EDK II project

typedef
EFI_STATUS
(EFIAPI *EFI_BLOCK_READ)(
  IN EFI_BLOCK_IO_PROTOCOL          *This,
  IN UINT32                         MediaId,
  IN EFI_LBA                        Lba,
  IN UINTN                          BufferSize,
  OUT VOID                          *Buffer
  );


struct _EFI_BLOCK_IO_PROTOCOL {
  ///
  /// The revision to which the block IO interface adheres. All future
  /// revisions must be backwards compatible. If a future version is not
  /// back wards compatible, it is not the same GUID.
  ///
  UINT64              Revision;
  ///
  /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
  ///
  EFI_BLOCK_IO_MEDIA  *Media;

  EFI_BLOCK_RESET     Reset;
  EFI_BLOCK_READ      ReadBlocks;
  EFI_BLOCK_WRITE     WriteBlocks;
  EFI_BLOCK_FLUSH     FlushBlocks;

};

_EFI_BLOCK_IO_PROTOCOL结构包含4个函数指针成员。

假设您有一个变量struct _EFI_BLOCK_IO_PROTOCOL * pStruct,并且您希望使用旧的*运算符来调用它的成员函数指针。你最终会得到这样的代码:

(*pStruct).ReadBlocks(...arguments...)

但是使用->运算符,您可以这样写:

pStruct->ReadBlocks(...arguments...)

哪个看起来更好?

答案 10 :(得分:1)

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

输出为5           5 5

答案 11 :(得分:0)

Dot是一个解除引用运算符,用于连接特定结构记录的结构变量。 例如:

struct student
    {
      int s.no;
      Char name [];
      int age;
    } s1,s2;

main()
    {
      s1.name;
      s2.name;
    }

通过这种方式,我们可以使用点运算符来访问结构变量