如果你采用
"黄金法则"(这不仅适用于指针),那么在C/C++中声明变量时,自然、直观且避免了
许多错误和
陷阱。不应违反“黄金法则”(有一些特例,如应用于数组typedef的
const
,它会将
const
传播到基本类型,以及C++引用)。
K&R,附录A,第8.4节,声明符的含义。
每个声明符都被视为一种断言:当与声明符相同形式的构造出现在表达式中时,它会产生指定类型和存储类别的对象。
在C/C++中声明变量时,您应该考虑应用于其上以获取基本类型的表达式。
1)必须有一个变量名称
2)然后是作为有效*的表达式,从声明语句中应用于变量名称
3)然后是声明的剩余信息和属性,如基本类型和存储
存储不是您总是可以赋予表达式结果的特征,与const性质相反。它只在声明时才有意义。因此,存储必须出现在不是2的其他地方。
int * const *pp;
int * static *pp;
我认为K&R希望我们在声明变量时使用倒推的方法,这通常不是一种常见的习惯。当使用时,它可以避免大多数复杂的声明错误和困难。
*valid并不是严格意义上的,因为会出现一些变化,比如x[]、x[size](不是索引)、constness等等...所以2是一个表达式,很好地映射(用于声明使用),"相同的形式",一个反映变量使用,但不是严格的。
未经训练者的黄金法则奖励
#include <iostream>
int (&f())[3] {
static int m[3] = {1, 2, 3};
return m;
}
int main() {
for(int i = 0; i < sizeof(f()) / sizeof(f()[0]); ++i)
std::cout << f()[i] << std::endl;
return 0;
}
在声明的上下文中,
&
不是获取地址的操作,它只是告诉我们这是一个引用。
f()
: f
是一个函数
&
返回值:其返回值是一个引用
- 引用
[3]
:该引用指向一个3个元素的数组
int
array[i]:一个元素是一个int
因此,您有一个返回到3个整数数组的引用的函数,并且由于我们具有数组大小的正确编译时信息,因此我们可以随时使用
sizeof
检查它=)
最后的黄金提示是,对于可放置在类型之前的任何内容,在多个声明中使用时,应同时应用于所有变量,因此无法逐个应用。
无法将此
const
放在
int
之前:
int * const p;
所以以下是有效的:
int * const p1, * const p2;
这个可以:
int const *p; // or const int *p;
所以下面是无效的:
int const *p1, const *p2;
可交换的
const
应适用于所有内容:
int const *p1, *p2; // or const int *p1, *p2;
声明约定
因此,我总是把所有不能放在类型前面的内容放在离变量更近的地方(int *a
, int &b
),而任何可以放在前面的内容,我都放在前面(volatile int c
)。
关于这个主题还有更多内容,请访问http://nosubstance.me/post/constant-bikeshedding/。
e
和i
是不合法的?因为它们声明了一个静态指针。指针可以具有静态生命周期。 - Thomas Matthewse
和i
被拒绝;其余被接受)。 - James McNellis