为什么大多数C程序员都将变量命名为:
int *myVariable;
而不是像这样:
int* myVariable;
两者都有效.在我看来,星号是类型的一部分,而不是变量名称的一部分.谁能解释这个逻辑?
它们完全等同.但是,在
int *myVariable, myVariable2;
很明显,myVariable的类型为int*,而myVariable2的类型为int.在
int* myVariable, myVariable2;
似乎很明显两者都是int*类型,但是因为intmyVariable2
类型不正确.
因此,第一种编程风格更直观.
如果你以另一种方式看待它,那*myVariable
就是类型int
,这是有道理的.
因为*更接近变量而不是类型:
int* varA, varB; // This is misleading
然而,即使是最好的单行声明对我来说也是违反直觉的,因为*是该类型的一部分.我喜欢这样做:
int* varA; int varB;
像往常一样,代码越紧凑,可读性越强.;)
到目前为止,没有人在这里提到的是这个星号实际上是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 *myVariable;
.要了解原因,请查看如何在C中声明其他类型的符号:
int my_function(int arg);
一个功能;
float my_array[3]
对于一个数组.
一般模式,称为声明跟随使用,是符号的类型被分割成名称前面的部分,以及名称周围的部分,名称周围的这些部分模仿您将用于获取的名称左侧类型的值:
int a_return_value = my_function(729);
float an_element = my_array[2];
并且:int copy_of_value = *myVariable;
.
C++在引用中抛出了一个扳手,因为在使用引用时的语法与值类型的语法相同,所以你可以说C++对C采用不同的方法.另一方面,C++保留相同的在指针的情况下C的行为,所以在这方面引用确实是奇怪的.
这只是一个偏好问题.
当您阅读代码时,在第二种情况下区分变量和指针会更容易,但是当您将一个常见类型的变量和指针放在一行中时可能会导致混淆(本身通常不鼓励项目指南,因为降低了可读性).
我更喜欢用类型名称旁边的相应符号声明指针,例如
int* pMyPointer;
在K&R中,它们将指针运算符放在变量名称旁边而不是类型.就个人而言,我认为这本书是最终的C权威/圣经.同样来自Objective-C背景,我遵循*name约定.
一位伟大的大师曾经说过"你必须按照编译器的方式阅读它."
http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835
当然这是关于const放置的主题,但同样的规则适用于此.
编译器将其读取为:
int (*a);
不是:
(int*) a;
如果您养成将星形放在变量旁边的习惯,它将使您的声明更容易阅读.它还避免了眼睛,如:
int* a[10];