当我声明C ++变量时,我这样做:
int a,b,c,d;
或
string strA,strB,strC,strD;
即,首先是类型,然后是逗号分隔的变量名列表。
但是,我声明了这样的指针:
int *a,*b,*c,*d;
和这样的引用:
int &a,&b,&c,&d;
为了保持一致,它应该是
int* a,b,c,d;
和
int& a,b,c,d;
为什么不一致?
答案 0 :(得分:11)
这是因为C传承。 *
修饰符适用于C中的变量。因此,C ++设计者将&
应用于变量以及类比,因为它们无法在不破坏C兼容性的情况下更改第一个变量。数组语法也是如此:
int anInt, *aPointerToInt, anArrayOfInt[100];
C ++的设计和演变 Bjarne Stroustrup表示他对此并不满意,但不得不接受C兼容性。他特别不满意这一点:
int *a[10];
从声明中不清楚a
是否是指向数组或指针数组的指针(它是一个指针数组,你需要用括号覆盖)。
当然,你总是可以使用typedef
来清理一下。
答案 1 :(得分:10)
我见过的最好的答案为什么类似*
之类的内容适用于变量,而不适用于类型{@ 3}}。
基本上,声明变量的方式应与使用变量的方式类似。
例如,
int *a, b;
...
*a = 42;
b = 314159;
...使用a
和b
看起来类似于a
和b
的声明。
C的创造者之一Dennis Ritchie甚至引用了这种行为:
类比推理导致了一个声明语法,用于反映名称通常出现的表达式语法的名称...在所有这些情况下,变量的声明类似于在表达式中的用法,该表达式的类型是在声明负责人。
答案 2 :(得分:7)
原因是:实际上C和C ++中的&
和*
适用于变量而不适用于类型。
所以问题是如果你想要声明4指向整数的指针你应该写
int *a, *b, *c, *d;
写int* a, b;
表示
int *a;
int b;
出于这个原因,很多人更喜欢写int *a;
而不是int* a;
,只是代码风格。
当然int*
是一种类型,但C语法清楚地表明在变量声明中*
和&
将适用于变量。
出现这种情况的原因与C中的数组以这种方式声明的相同:
int a[10], b;
std::cout << typeid(a).name() << std::endl; // it will print int[10]
std::cout << typeid(b).name() << std::endl; // it will print int
在C#等其他语言中,使用了语法int[] array;
。
另一件事是指向函数语法的指针:
// Now we declare a variable that is a pointer to function
int (*pt2Function)(char, char) = NULL;
我们正在将*
应用于变量名称。
在我看来,使用*
和&
应用于变量,如果我们90%的人更喜欢不同的话,则与语言的其他部分更加一致。
以同样的方式,回到数组:
// Now we declare a variable that is a pointer to an array of 10 integers.
int (*arrayptr)[10];
答案 3 :(得分:4)
C对其声明有一个规则:声明模仿使用。这意味着变量的声明看起来像变量的使用方式。例如:
int i;
使用此变量看起来像i
,该表达式会产生int
。
int *i;
使用此变量看起来像*i
,该表达式会产生int
。这也意味着表达式i
会生成指向int
的指针。
int i(void);
使用此变量看起来像i()
,并产生int
。这也意味着i
是一个不带任何东西并返回int
的函数。
int (*i[5])();
使用此变量看起来像(*i[x])()
,并产生int
。这也意味着*i[x]
是一个返回int
的函数,i[x]
是指向返回int
的函数的指针,而i
是一个指向函数的指针数组返回int
。
所以:
int a, *b, c(void), (*d[5])(void);
声明了几个都具有int
类型的表达式,但变量本身并非都是int
。
N.B。在函数和数组的声明中,子声明并不完全类似于变量的使用。即int i[5];
并不意味着您在使用i
时需要在方括号内放置“5”,int i(int);
并不意味着您通过说{{1}来调用该函数}}。此外,结构类型变量的声明与它们的使用不匹配,因为您必须为每个成员变量声明表达式。
与声明变量的语法相关的是typedef的语法。要声明具有特定类型的typedef,可以使用与声明所需类型的变量相同的语法,但是在声明前加上i(int);
,变量名称变为typedef名称。
typedef
C ++添加了引用,模板,指向成员的指针以及一堆东西。它试图在某种程度上遵循旧的C约定,但是对于C ++添加的许多东西,该约定并没有真正起作用,所以你开始得到不一致。你只需要学习这些特性,并将其归结为C和C ++之间不完美的结合。
答案 4 :(得分:2)
C ++从C继承了这种语法.K&amp; R书(§5.1)说表达式
int *ip, **ipp;
意图是助记符(即您阅读“*ip
而**ipp
具有类型int
”),他们希望它模仿使用语法。
我同意它对人类来说非常神秘且违反直觉,并且与typedef不一致,例如
typedef int* intptr;
intptr a, b; // equivalent to: int *a, *b
但它从来就不是C ++作者的决定,使用这种语法暗示语言与C兼容的选择,这就是原因。