Bjarne解释了为什么const可以在类型之前或之后进行。
http://www.stroustrup.com/bs_faq2.html#constplacement
"const T" and "T const" were - and are - (both) allowed and equivalent. [...]
为什么呢?当我发明“const”(最初命名为“readonly”并且有一个 相应的“writeonly”),我允许它在之前或之后去 因为我可以毫不含糊地这样做。
我的直接想法是,“好吧,这是有道理的,但如果这就是为什么const特别?”显然它不是。 clang和gcc都没有发出以下警告。
int volatile myint;
int static myotherint;
这是有道理的,这是有效的,但我从未见过这种语法,甚至提到过这种可能性。在类型有效的C ++之后放置静态和易失性限定符吗?
如何从标准文本中确定这一点?
答案 0 :(得分:4)
是的,语法很好。声明语法的第一部分是 decl-specifiers 的序列。这些包括存储类指定,类型说明符,函数指定,friend
,typedef
和constexpr
。语法允许它们以任何顺序出现。但是,放在它们上的语义规则引入了一些限制。例如,在变量声明中,必须始终有一个不是cv限定符(const
或volatile
)的类型说明符。也绝不能有多个存储类说明符(thread_local
除外static
或extern
)。
请注意,decl-specifiers的序列出现在任何复合类型语法之前,例如指针,引用,数组等。例如,decl-specifiers序列在以下示例中标记:
static const int *p;
| |
char volatile static *(&p)[20];
| |
请注意,volatile
是一个cv限定符,例如const
,因此您提供的示例中允许volatile
的原因与const
相同。这些关键字也可以在声明中更深入地显示(如int *volatile x;
)。
按照惯例,我们首先编写存储类指定,然后在适当的地方使用类型指定和cv限定符。我更喜欢在它们对应的类型说明符之后编写我的cv-qualifications ,因为它更加一致。
您可能希望阅读What are declarations and declarators and how are their types interpreted by the standard?。
答案 1 :(得分:2)
这些作品在标准中实际上相当广泛。 static
是一个存储类,如§7.1.1/ 1中所述:
storage-class-specifier:
register
static
thread_local
extern
mutable
用于 decl-specifier ,如§1.7中所定义:
decl-specifier:
storage-class-specifier
type-specifier
function-specifier
friend
typedef
constexpr
decl-specifier-seq:
decl-specifier attribute-specifier-seqopt
decl-specifier decl-specifier-seq
因此,这允许static int
或int static
指定类型。同样,您可以将朋友函数声明为friend int f();
或int friend f();
。
const
或volatile
只能在您实际声明某些内容时参与其中,因此它属于第8节中的“声明者”。这部分语法足够长,我懒得格式化这一切,但它在顶级指定 init-declarator-list ,然后声明符,并且(跳过几个级别)下降到cv-qualifier
,这是const
或volatile
。至少通过我的阅读,它基本上允许const
或volatile
与指定类型的其他内容自由混合。
答案 2 :(得分:0)
嗯,以下是我猜的。我试着解释这个。
static int *ptr1;
int* static ptr2;
第一个意味着它是一个指针,指向一个静态整数。 第二个意味着它是一个静态变量,具有整数指针类型。
我认为另一种方式应该有类似的解释。