为什么大多数C程序员这样命名变量:

int *myVariable;

而不是像这样:

int* myVariable;

两者都成立。在我看来,星号是类型的一部分,而不是变量名的一部分。有人能解释一下这个逻辑吗?


当前回答

一位伟大的大师曾经说过:“你必须按照编译器的方式来阅读它。”

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

虽然这是关于const放置的主题,但同样的规则也适用于这里。

编译器将其解读为:

int (*a);

而不是:

(int*) a;

如果您养成了将星号放在变量旁边的习惯,它将使您的声明更容易阅读。它还避免了一些碍眼的东西,比如:

int* a[10];

——编辑——

为了准确解释我说它被解析为int (*a)时的意思,这意味着*与a的绑定比与int的绑定更紧密,就像在表达式4 + 3 * 7中,3与7的绑定比与4的绑定更紧密,因为*的优先级更高。

为了对ascii艺术表示歉意,解析int *a的A.S.T.大致如下所示:

      Declaration
      /         \
     /           \
Declaration-      Init-
Secifiers       Declarator-
    |             List
    |               |
    |              ...
  "int"             |
                Declarator
                /       \
               /        ...
           Pointer        \
              |        Identifier
              |            |
             "*"           |
                          "a"

如图所示,*与a的绑定更紧密,因为它们的共同祖先是Declarator,而您需要沿着树一直向上走到Declaration才能找到涉及int的共同祖先。

其他回答

如果你从另一个角度来看,*myVariable是int类型,这是有意义的。

到目前为止还没有人提到的是,这个星号实际上是C语言中的“解引用操作符”。

*a = 10;

上面这行并不是说我要把10赋值给a,而是说我要把10赋值给a所指向的任何内存位置。我从没见过有人在写作

* a = 10;

有你吗?所以解引用操作符总是没有空格。这可能是为了将它与跨多行分解的乘法区分开来:

x = a * b * c * d
  * e * f * g;

这里*e会误导人,不是吗?

好吧,下面这行到底是什么意思:

int *a;

大多数人会说:

这意味着a是一个指向int值的指针。

这在技术上是正确的,大多数人喜欢这样看/读它,这就是现代C标准定义它的方式(注意,C语言本身早于所有ANSI和ISO标准)。但这并不是看待它的唯一方式。你也可以这样读这句话:

a的解引用值是int类型的。

所以事实上,这个声明中的星号也可以被看作是一个解引用操作符,这也解释了它的位置。a是一个指针其实并没有声明,它是一个隐含的事实,你唯一可以解引用的是一个指针。

C标准只定义了*操作符的两个含义:

间接操作符 乘法运算符

间接只有一个含义,声明指针没有额外的含义,只有间接,这就是解引用操作的作用,它执行间接访问,所以在像int *a这样的语句中;这是一种间接访问(*表示间接访问),因此上面的第二个语句比第一个语句更接近标准。

一位伟大的大师曾经说过:“你必须按照编译器的方式来阅读它。”

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

虽然这是关于const放置的主题,但同样的规则也适用于这里。

编译器将其解读为:

int (*a);

而不是:

(int*) a;

如果您养成了将星号放在变量旁边的习惯,它将使您的声明更容易阅读。它还避免了一些碍眼的东西,比如:

int* a[10];

——编辑——

为了准确解释我说它被解析为int (*a)时的意思,这意味着*与a的绑定比与int的绑定更紧密,就像在表达式4 + 3 * 7中,3与7的绑定比与4的绑定更紧密,因为*的优先级更高。

为了对ascii艺术表示歉意,解析int *a的A.S.T.大致如下所示:

      Declaration
      /         \
     /           \
Declaration-      Init-
Secifiers       Declarator-
    |             List
    |               |
    |              ...
  "int"             |
                Declarator
                /       \
               /        ...
           Pointer        \
              |        Identifier
              |            |
             "*"           |
                          "a"

如图所示,*与a的绑定更紧密,因为它们的共同祖先是Declarator,而您需要沿着树一直向上走到Declaration才能找到涉及int的共同祖先。

这只是个人喜好的问题。

当您阅读代码时,在第二种情况下,区分变量和指针更容易,但是当您将同一类型的变量和指针放在一行中时,可能会导致混淆(项目指南通常不鼓励这样做,因为这会降低可读性)。

我更喜欢在类型名旁边声明指针的对应符号,例如。

int* pMyPointer;

对于在一行中声明多个指针,我更喜欢int* a, * b;它更直观地将“a”声明为指向整数的指针,并且在同样声明“b”时不会混合样式。就像有人说的,我不会在同一个语句中声明两种不同的类型。