在C语言中,箭头操作符(->)的用法

12 浏览
0 Comments

在C语言中,箭头操作符(->)的用法

我正在阅读一本名为《21天自学C语言》的书(我已经学过Java和C#,所以我进展得更快)。我正在阅读指针章节,其中涉及到一个没有解释的->(箭头)操作符。我认为它用于调用成员和函数(类似于.(点)操作符,但用于指针而不是成员)。但我并不完全确定。\n可以给我一个解释和一个代码示例吗?

0
0 Comments

箭头操作符(->)在C语言中的用法

在C语言中,箭头操作符(->)用于通过指针访问结构体的成员。为什么需要引入这个操作符呢?

"."是标准的成员访问操作符,它的优先级高于"*"指针操作符。当你试图访问一个结构体的内部成员,并且将其写为 *foo.bar 时,编译器会认为你想要访问一个名为'bar'的元素,但是'foo'是一个内存地址,显然这个地址本身没有任何成员。

因此,你需要告诉编译器先解引用 foo,然后再访问成员元素:(*foo).bar。然而这种写法有点繁琐,所以好心的程序员们想出了一个简写版本:foo->bar,这种写法类似于通过指针访问成员的操作符。

解决方法就是使用箭头操作符(->)来代替点操作符(.),这样就可以直接通过指针访问结构体的成员了。这个操作符的使用方法是:指针->成员名。

例如,如果有一个结构体指针 foo,它指向一个具有成员 bar 的结构体,你可以使用 foo->bar 来访问 bar 成员。

这就是箭头操作符(->)的原因和解决方法。通过使用箭头操作符,我们可以更方便地通过指针访问结构体的成员,避免了繁琐的解引用操作。

希望这篇文章对你理解箭头操作符(->)的使用有所帮助!

0
0 Comments

在C语言中,箭头运算符(->)用于访问指针类型的结构体或类的成员。它的出现是为了区分指针和引用类型的结构体或类的成员访问。

在上述代码中,声明了一个结构体foo,包含两个成员变量x和y。首先通过var.x和var.y来访问var结构体的成员变量,因为var是一个结构体的实例。

接下来,声明了一个指向结构体foo的指针pvar,并通过pvar->y来访问pvar指向的结构体的成员变量y。这里使用箭头运算符->而不是点运算符.,是因为pvar是一个指针类型,而不是引用类型。

同时,代码中还出现了一个问题:pvar指针未初始化,如果想让pvar指向一个新的结构体,而不是指向var结构体,该如何初始化pvar呢?在C语言中没有类或引用变量的概念,因此无法像C++中那样直接使用new关键字来创建对象。解决这个问题的方法是使用malloc函数动态分配内存,将分配的内存地址赋给pvar指针,使其指向一个新的结构体。可以使用 pvar = malloc(sizeof(struct foo)); pvar = malloc(sizeof(*pvar)); 来完成初始化。

此外,还有一个提醒,在写入pvar->y之前应该先为pvar分配内存,否则会写入未分配的内存空间。可以通过手动初始化所有成员变量或使用calloc函数进行零填充来解决这个问题。

,箭头运算符(->)的出现是为了方便访问指针类型的结构体或类的成员,解决方法是使用malloc函数动态分配内存并初始化指针,同时要注意写入成员变量之前要先为指针分配内存。

0
0 Comments

Arrow operator (->) usage in C

在C语言中,箭头操作符(->)用于访问指针所指向的结构体成员。它等价于(*foo).bar,即从指针foo指向的结构体中获取名为bar的成员。

值得注意的是,如果解引用操作符被设计为后缀操作符(如Pascal语言),那么箭头操作符就不再需要了,因为它可以等价于更加易读的foo*.bar。这也避免了使用typedef定义函数时需要添加额外括号的麻烦。

那么foo*.bar和(*foo).bar是否等价于foo->bar呢?如果是指针的话,Foo myFoo = *foo; myFoo.bar又是什么意思呢?

不,他只是在说如果C语言的创建者将解引用操作符设计为后缀操作符而不是前缀操作符,那么会更加简单。但实际上C语言中解引用操作符是前缀操作符。

你能否简要描述或提供链接关于你提到的“使用额外括号进行typedef函数声明”的内容?谢谢。

不,那样会导致更多的括号。目前,括号和方括号的优先级高于解引用操作符,位于左边的*。如果它们都位于同一边,你将需要更多的括号。在表达式中也是如此,因为与乘法操作符冲突。Pascal的^也可以是一种选择,但它被保留用于位操作,仍然需要更多的括号。

但为什么需要显式解引用呢?既然一个类型不能同时是指针和结构体,为什么不能在foo已知是指针的情况下,将foo.bar自动展开为(*foo).bar呢?(然后如果*foo本身是指针,再展开为(*(*foo)).bar等等)

从技术上讲,语言设计者完全可以在这种情况下将解引用操作隐式化(Rust语言在这种情况下和其他情况下都这样做),但他们没有这样做。可能是因为他们认为代码中所有的解引用应该是显式的,和/或者他们希望保持语言规则尽可能简单。注意,C++智能指针有它们自己的方法(如shared_ptr的use_count()),因此在这种情况下需要区分在指针上调用方法和在指向的对象上调用方法,但这当然不会对C的设计产生影响。

0