我目前正在学习C,通过阅读一本名为“21天自学C”的优秀初学者的书(我已经学习了Java和C#,所以我的学习速度要快得多)。我正在读关于指针和 - >的章节。 (箭头)操作员没有解释就上来了。我认为它用于调用成员和函数(比如。(点)运算符,但是用于指针而不是成员)。但我不完全确定。我可以获得解释和代码示例吗?
答案 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;
在这里,为了访问i
和j
的值,我们可以使用变量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>您添加一个偏移量(标识符)以选择成员。
检查我制作的这张图片:
但是,如果您有嵌套成员,则该语法将变得不可读,因此引入了->
。我认为可读性是使用它的唯一正当理由,因为此ptr->kg
比(*ptr).kg
更容易编写。
现在,让我们以不同的方式写这个,以便您更清楚地看到连接。 (*ptr).kg
⟹(*&audi).kg
⟹audi.kg
。在这里,我首先使用ptr
是“ audi
” 的地址(即&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;
}
通过这种方式,我们可以使用点运算符来访问结构变量