【问题标题】:Arrow Operator vs. Dot Operator [closed]箭头运算符与点运算符 [关闭]
【发布时间】:2012-04-19 15:39:11
【问题描述】:

在我看来,C 的箭头运算符 (->) 是不必要的。点运算符 (.) 应该足够了。取以下代码:

typedef struct {
    int member;
} my_type;

my_type   foo;
my_type * bar;
int       val;

val = foo.member;
val = bar->member;

我们看到必须使用箭头操作符来取消对 bar 的引用。但是,我更喜欢写

val = bar.member;

关于我是试图从结构中提取“成员”还是从指向该结构的指针中提取“成员”,这一点没有歧义。但是很容易使用错误的运算符,尤其是在重构代码时。 (例如,也许我正在对 foo 进行一些复杂的操作,所以我将代码移动到一个新函数中并传递一个指向 foo 的指针)。我认为我不需要关心 foo 是否是指针;编译器可以担心细节。

那么问题来了:从 C 语言中删除 -> 不是更简单吗?

【问题讨论】:

  • 今天有数十亿行 C 代码在使用。从 C 语言中删除任何内容并不容易。也就是说,关于间接的明确性是一件好事。
  • 你说得对,没必要。它是(*bar).member 的语法糖。根据定义,我们不需要任何语法糖。再说一次,我们也不需要 函数。我们可以goto做所有事情。
  • 是的,但它似乎是语法糖,它使事情变得更难而不是更容易。另一方面,函数很方便。 :)
  • 在 Rust 编程语言中,. 运算符在访问 struct 字段之前根据需要取消引用尽可能多的指针层。它完全符合您在此线程中的要求。

标签: c pointers structure


【解决方案1】:

“箭头”运算符是语法糖。 bar->member(*bar).member 相同。造成差异的原因之一是可维护性。箭头运算符与点运算符不同,跟踪哪些变量是指针,哪些不是指针变得容易得多。可能始终使用. 并让编译器尝试做正确的事情,但我怀疑这会使语言更简单。相信编译器会解释你的意思意思而不是你字面上写的通常结果很糟糕。

【讨论】:

  • 更不用说像指针一样起作用的类(提供*-> 运算符),但. 也是一个有效的操作。
  • @jpm:C 没有类。但是,您有一个观点,因为这会引入对 C++ 的不必要的不​​兼容性(出于您所说的原因,可能不会采用该约定)。
  • 如果member 本身就是一个结构,那么(*). 之间的等价关系是否仍然适用?例如bar→member→value(*bar).member→value 一样,但是bar→(*member).value 不同(实际上是编译错误)。
  • @MaxCoplan 如果member 是一个结构,则不能将* -> 运算符应用于它。 bar->member->value(*bar).member->value 都是错误的。唯一正确的方法是bar->member.value(*bar).member.value
  • @MaxCoplan 是的,这两种形式仍然是等价的,但是运算符优先级很快就会使事情变得非常丑陋且容易出错(.-> 绑定高于 *)。 a->b->c 将变为 (*(*a).b).c。你真的不想在多层次的场景中写出很长的路要走。
【解决方案2】:

不,从语言中删除->更容易,原因很简单,如果需要,就必须重写大量代码。然而,如果p 是一个指针,则可以定义p.x 等价于p->x。这将是一个向后兼容的更改,因为该代码当前是非法的。

【讨论】:

  • 是的,但正如@bta 所提到的,这将是一个不明智的改变。 -> 有助于确定哪些变量是值,哪些是指针,这反过来又有助于保持内存管理的可维护性。
猜你喜欢
  • 2013-07-16
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多