为什么大多数C程序员这样命名变量:
int *myVariable;
而不是像这样:
int* myVariable;
两者都成立。在我看来,星号是类型的一部分,而不是变量名的一部分。有人能解释一下这个逻辑吗?
为什么大多数C程序员这样命名变量:
int *myVariable;
而不是像这样:
int* myVariable;
两者都成立。在我看来,星号是类型的一部分,而不是变量名的一部分。有人能解释一下这个逻辑吗?
当前回答
它们是完全相等的。 然而,在
int *myVariable, myVariable2;
显然,myVariable的类型是int*,而myVariable2的类型是int。 在
int* myVariable, myVariable2;
很明显,两者都是int*类型,但这是不正确的,因为myVariable2的类型是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这样的语句中;这是一种间接访问(*表示间接访问),因此上面的第二个语句比第一个语句更接近标准。
因为这一行中的*与变量的绑定比与类型的绑定更紧密:
int* varA, varB; // This is misleading
正如@Lundin在下面指出的,const增加了更多需要考虑的微妙之处。你可以通过每行声明一个变量来完全避免这个问题,这永远不会有歧义:
int* varA;
int varB;
清晰的代码和简洁的代码之间的平衡是很难实现的——十几行冗余的int a;也不好。不过,我还是默认每行声明一次,并担心以后组合代码的问题。
如果你从另一个角度来看,*myVariable是int类型,这是有意义的。
一位伟大的大师曾经说过:“你必须按照编译器的方式来阅读它。”
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 *myVariable;。要理解其中的原因,看看如何在C语言中声明其他类型的符号:
Int my_function(Int arg);对于一个函数;
为数组浮动my_array[3]。
一般的模式,被称为声明遵循使用,是一个符号的类型被分为名称前的部分和名称周围的部分,而名称周围的这些部分模仿了你用来获得左侧类型值的语法:
Int a_return_value = my_function(729);
浮动an_element = my_array[2];
and: int copy_of_value = *myVariable;
c++在引用方面遇到了麻烦,因为使用引用的语法与值类型的语法是相同的,所以你可能会说c++采取了与C不同的方法。另一方面,c++在指针的情况下保留了与C相同的行为,所以引用在这方面确实是一个奇怪的例子。