为什么它认为’T * name’是C方式而’T * name’是C ++方式?

注意:这个问题是关于星号( * )的位置。

在大多数C代码中,我看到(例如,在Beej的网络编程指南中 ),所有变量声明/定义都使用T *name格式,即将*绑定到变量名称。 指针被认为属于变量,而不是类型。

在我看到的大多数C ++代码中,格式是T* name ,即它将*绑定到变量的类型。 指针被认为属于类型,而不是变量。 我自己,作为一个纯粹的C ++编码器,也使用这种格式,因为指针类型清楚(对我来说)属于类型,而不是变量。 (很明显,即使是C ++标准也在示例中使用了这种格式。:))

这有(历史性的)原因吗? 当程序员开始做C ++时,思维方式是否有所改变?

如果一个C编码器(使用前一种格式)可以解释他/她使用它的原因,而不是后者,那也很好。

来自Stroustrup的C ++风格和技巧常见问题解答 。

“典型的C程序员”写入int *p; 并解释它“ *p是什么是int ”强调语法,并可能指向C(和C ++)声明语法来争论样式的正确性。 实际上, *与语法中的名称p绑定。

“典型的C ++程序员”写入int* p; 并解释它“ p是指向int的指针”强调类型。 实际上, p的类型是int* 。 我显然更喜欢这种强调,并认为它对于使用C ++的更高级部分非常重要。

如果我冒险猜测,我会说这是因为C ++人更有可能认为类型信息本身就是一种东西,因为模板可以在编译时以编程方式操作类型。 它们也不太可能在同一个声明中声明几个变量。

T*风格将类型信息集中在一个地方并使其脱颖而出,以及由T* foo, bar;等引入的混乱T* foo, bar; 如果您从未在同一语句中声明两个变量,则使用此语法不会出现问题。

就个人而言,我发现T*风格真的很讨厌,并且非常不喜欢它。 *是类型信息的一部分,它是真的,但编译器解析它的方式使它实际上附加到名称,而不是类型。 我认为T*方式掩盖了正在发生的重要事情。

在我的观察中,似乎我在C ++社区中很少见。 我注意到你对最流行的风格有同样的看法。

当然,要明确这两种风格都适用于任何一种语言。 但我确实注意到你做了同样的事情,一种风格在C代码中往往更常见,另一种在C ++中更常见。

就个人而言,我不同意这一点 – 我不认为有这样做的C或C ++方式。 我从未见过有任何证据表明这一点。 但是,我确实假设为什么星号的语法更靠近C中声明的变量名。

在C中(至少在C89中,绝大多数C在使用中),您必须在块的顶部声明所有变量。 这导致程序员在做

 T a, b, c; 

相对而言,在C ++中,这种情况很少见。 (在C ++中,您声明变量接近于它们的使用位置,变量通常具有构造函数参数等;因此很少在一行上声明多个对象)

这也恰好是语法很重要的唯一情况,因为声明

 T* a, b, c; 

声明一个指针,而不是程序员可能期望的那三个。

由于在一行中放置多个声明在C中更常见,并且也是唯一一个星号位置很重要的情况,程序员更有可能将星号与变量相关联。

也就是说,我从未见过任何证据 – 这只是猜想。

有几个人提到了非常好的观点。 我只想指出,虽然C非常强烈地保留了“声明反映使用”的含义,但C ++却没有。 C ++中的几个声明符不反映声明中的用法;

 int &ref; // but "&ref" has type "int*", not "int". int &&ref; // but "&&ref" is not valid at all. 

我不认为编写它的C ++程序员实际上有这个原因,但它可能会阻止C ++书籍作者提及它,这可能会影响那些C ++程序员。

C程序员倾向于使用一种风格而C ++程序员使用其他风格的原因很简单:Kernighan和Ritchie在他们的书中使用了“C风格”,而Stroustrup在他的书中使用了“C ++风格”。

在K&R中,他们使用type *name表示法,因此可能是许多C程序员得到它的地方。

因为Bjarne有后见之明的好处:他意识到C声明符语法是“失败的实验”(读:C声明符语法被延迟)。 其他人已经得到了其他人的回答。

我不认为你对你的区别是正确的,

T *风格的C ++ 代码 。

T*风格的C 代码 。

我认为这只是项目参与者个人偏好的问题。

只是在这个问题上引起一些争议:

  • C ++用户通常声明每行一个声明可以将星号放在类型上(左侧)。 int* a; int* b;
  • C和C ++都使用附在名称​​上的星号(右侧)进行解析。 int *a;
  • C ++预处理器通常将星号移到左侧。 C预处理器将其移动到右侧。
  • 在任何一种语言中,将它放在左边对于在同一语句中声明相同类型的多个变量看起来很奇怪。 int* a, * b, * c;
  • 在左边有一些看起来很愚蠢的句法元素。 int* (* func)()

还有其他C元素被错误使用,例如const ,它也属于右侧! int const a; 。 这通常放在类型的左侧,尽管属于左侧的类型。 必须修改许多编译器来处理这种用法。 在C ++中,您可以观察到这与常量方法一致,因为编译器无法推断它是否放在左侧: int A::a() const 。 这也与使用constrestricted朋友以及诸如int const *类的声明的嵌套用法分解。 const常规用法表明这是一个指向整数的常量指针,但实际上它是int *const

TL;博士

你们一直都在做错,把一切都放在右边。

C声明遵循与表达式相同的规则(例如优先级)。 事实上,考虑像这样的声明是完全有效的

 int *foo; 

将表达式*foo (即应用于foo的间接运算符)的类型声明为int而不是foo作为int*类型。

然而 – 正如其他已经指出的那样 – 在C ++中,将类型视为单独的,并且 – 由于模板 – 可修改的实体,因此使用类似的声明是有意义的

 int* foo;