在指针声明中放置星号
我最近决定,我不得不最终学习C / C ++,有一点我不太了解指针,或者更确切地说,他们的定义。
这些例子如何:
int* test;
-
int *test;
-
int * test;
-
int* test,test2;
-
int *test,test2;
-
int * test,test2;
现在,据我了解,前三种情况都是一样的:testing不是一个int,而是一个指针。
第二套例子有点棘手。 在情况4中,test和test2都是指向int的指针,而在情况5中,只有test是一个指针,而test2是一个“真实的”int。 那么情况6呢? 与案例5一样?
4,5和6是一样的东西,只有testing是一个指针。 如果你想要两个指针,你应该使用:
int *test, *test2;
或者,甚至更好(使一切都清楚):
int* test; int* test2;
星号周围的空白没有意义。 所有三个意思是相同的事情:
int* test; int *test; int * test;
“ int *var1, var2
”是一个邪恶的语法,只是为了混淆人,应该避免。 它扩展到:
int *var1; int var2;
使用“顺时针螺旋规则”来帮助parsingC / C ++声明;
有三个简单的步骤:
以未知元素开始,以螺旋/顺时针方向移动; 当生成以下元素时,用相应的英语语句replace它们:
[X]
或[]
:数组X的大小…或数组未定义的大小…
(type1, type2)
:函数传递type1和type2返回…
*
:指向…的指针- 继续以螺旋/顺时针方向进行操作,直到所有的令牌都被覆盖。
- 总是先解决任何括号内的问题!
此外,声明应尽可能在单独的声明(绝大多数情况下是这样)。
许多编码指南build议您只在每行声明一个variables 。 这样可以避免你在提出这个问题之前所做的任何混淆。 与我一起工作的大多数C ++程序员似乎都坚持这一点。
有一点我知道,但是我发现有用的是向后读取声明。
int* test; // test is a pointer to an int
这开始工作得很好,特别是当你开始声明const指针时,知道它是否是const的指针,或者指针指向的是const还是非常棘手。
int* const test; // test is a const pointer to an int int const * test; // test is a pointer to a const int ... but many people write this as const int * test; // test is a pointer to an int that's const
#include <type_traits> std::add_pointer<int>::type test, test2;
正如其他人提到的,4,5和6是一样的。 通常,人们用这些例子来说明*
属于variables而不是types。 虽然这是一个风格问题,但是你是否应该这样思考和写下这个问题呢?
int* x; // "x is a pointer to int"
或者这样:
int *x; // "*x is an int"
FWIW我在第一阵营,但其他人为第二种forms争论的原因是(主要)解决了这个问题:
int* x,y; // "x is a pointer to int, y is an int"
这可能是误导性的; 相反,你会写
int *x,y; // it's a little clearer what is going on here
或者如果你真的想要两个指针,
int *x, *y; // two pointers
就个人而言,我说每行保留一个variables,那么你更喜欢哪种风格并不重要。
在4,5和6中, test
总是一个指针,而test2
不是一个指针。 在C ++中,空白(几乎)是不重要的。
指针是types的修饰符。 为了更好地理解星号如何修改types,最好从右到左读取它们。 'int *'可以被读为“指向int的指针”。在多个声明中,你必须指定每个variables是一个指针,否则它将被创build为一个标准variables。
1,2和3)testing是types(int *)。 空白不重要。
4,5和6)testing是types(int *)。 Test2是inttypes的。 再次,空白是无关紧要的。
你可以认为4,5和6如下:声明types只需要做一次,但如果你想声明一个指向该types的指针(通过添加一个星号),你必须这样做每个variables。
当声明一个指针variables时,我总是在variables和星号之间加上空格,即使我在一行中声明了多个。 不这样做使得我几乎每次都把它混淆为一个解引用expression式。
一个好的经验法则是,很多人似乎都掌握了这些概念:在C ++中,很多语义含义是由关键字或标识符的左边绑定派生的。
举个例子:
int const bla;
const适用于“int”字。 指针的星号也是一样,它们适用于左侧的关键字。 而实际的variables名称? 是的,这是剩下的东西。
C语言的基本原理是你用variables的方式声明variables。 例如
char *a[100];
说*a[42]
将是一个char
。 还有a[42]
字符指针。 因此, a
是一个char指针数组。
这是因为原始的编译器编写者想要使用相同的parsing器来进行expression式和声明。 (语言deviseselect不是一个非常明智的理由)
我会说,最初的约定是将星形放在指针名称一侧(声明的右侧)
-
在丹尼斯·M·里奇(Dennis M. Ritchie) 的c编程语言中 ,星星在声明的右边。
-
通过查看https://github.com/torvalds/linux/blob/master/init/main.c中的linux源代码,我们可以看到这个明星也在右边。;
你可以遵循相同的规则,但是如果你把星星放在types方面,这并不是什么大问题。 请记住, 一致性是重要的,所以总是在同一方,而不pipe你select哪一方。
情况1,2和3是相同的,他们声明指向intvariables的指针。 例3,例4和例5是相同的,因为它们分别声明一个指针和一个intvariables。 如果你想要在一行中声明两个指针(你不应该这样做),你需要在每个variables名前加一个星号:
int *test, *test2;
没有什么正确的方法可以说明星号在哪里。 int* test
看起来更好,因为我们更容易想象在types末尾附加*
意味着“指向”types。 然而, int *test
更有意义,因为您可以像math中的减号一样使用它:
-(-x) = x
是类似的
*(*test) = test
这一直帮助我。 可悲的是,这一切的结果是,有时我使用int* test
和有时int *test
。