(*x).y和x->y是一样的吗?

5

在C语言中,是否允许使用->运算符代替.运算符?它的可用性是否取决于我们使用的编译器?->运算符是最新的C标准中可用的,还是来自C++标准?这两者有何不同?


4
是的。x->y(*x).y的简写。它从C语言一开始就可用。实际上,没有人会写(*x).y - Jabberwocky
除非 -> 被覆盖,如果我理解正确的话。 - bereal
@MichaelWalz 这不是速记法,只是用不同的方式完成相同的事情。 - There is nothing we can do
2
@bereal 在C语言中,你无法“覆盖”内置运算符。 - unwind
@unwind 这个问题被标记为 c++...好的,不再是了。 - bereal
5个回答

14
在C语言中,c->m等同于(*c).m。括号是必需的,因为.的优先级高于*。任何值得尊重的编译器都会生成相同的代码。
在C++中,除非->*重载,否则等价于上述内容。

@Lundin -> 是可重载的,Bjarne 希望在 C++17 中也使 . 可重载,以便拥有类似于智能指针的智能引用。详见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4477.pdf。 - bolov
@Lundin:我们将平分50/50。你不能覆盖 . - Bathsheba
1
C++ 给了你开枪自射的机会,这取决于你。当构建托管指针类时,重载 -> 可能是有用的。我最讨厌 Java 的一点是它不允许操作符重载。我发现与某些类(例如 BigInteger)一起工作非常令人沮丧。 - Bathsheba
2
@Lundin 重载 -> 在创建类似指针的类(比如 std::unique_ptr)时确实非常有用。另一方面,当你拥有 x 时,你需要 某种形式 的保证能够访问成员变量 y 或对象 x,因此必须保留一个无法重载的运算符。这个运算符就是 . - Angew is no longer proud of SO
2
@Bathsheba 不,自残是 C 语言。C++ 则是炸掉你的腿 :) Java 很无聊,因为没有华丽的爆炸效果。 - Lundin
显示剩余7条评论

5
这里有三个操作符,分别是*.->。这很重要,因为.->的优先级都是1,但*的优先级是2。因此,*foo.barfoo->bar不同,需要使用括号,例如(*foo).bar
所有这些都是原始的C运算符,并且已经存在了很长时间。

5
在C语言中,a->b(*a).b是完全等价的,引入->的原因是优先级——这样你就不必在(*a)中输入括号。
在C++中,operator *operator ->可以独立重载,因此不能再说a->b(*a).b在所有情况下都是等价的。然而,当a是内置指针类型时,它们仍然是100%等价的。

1
你是正确的,它们在理论上可能是不同的。实际上,我能想到唯一让它们不同的原因是作为国际混淆C++大赛的一个入门(这件事从未发生过——可能是因为没有挑战)。 - Martin Bonner supports Monica
1
@MartinBonner 或者它们可能是意外不同的。 当寻找难以捉摸的错误时,了解什么可以绝对地视为理所当然是很好的。其他所有内容都有可能是可疑的。 - Angew is no longer proud of SO

1

-> 操作符是 C 语言中的标准操作符。使用 .-> 都可以访问结构体字段。在结构体变量上使用 .,在结构体指针变量上使用 ->

struct foo {
    int x;
    int y;
}

struct foo f1;
f1.x = 1;
f1.y = 3;
struct foo *f2 = &f1;
printf("%d\n", f1.x);     // 1
printf("%d\n", f2->x);    // 1

“*” 运算符被称为“解引用运算符”,它返回指针地址上的值。因此,“(*f2).x” 等同于 “f2->x”。

0
通常情况下,编译器应该生成相同的代码。但是这些运算符可以被重载,因此有不同的功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接