类型后的静态和易失性限定符

时间:2014-08-20 22:54:36

标签: c++ language-lawyer qualifiers

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 ++之后放置静态和易失性限定符吗?

如何从标准文本中确定这一点?

3 个答案:

答案 0 :(得分:4)

是的,语法很好。声明语法的第一部分是 decl-specifiers 的序列。这些包括存储类指定,类型说明符,函数指定,friendtypedefconstexpr。语法允许它们以任何顺序出现。但是,放在它们上的语义规则引入了一些限制。例如,在变量声明中,必须始终有一个不是cv限定符(constvolatile)的类型说明符。也绝不能有多个存储类说明符(thread_local除外staticextern)。

请注意,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 intint static指定类型。同样,您可以将朋友函数声明为friend int f();int friend f();

constvolatile只能在您实际声明某些内容时参与其中,因此它属于第8节中的“声明者”。这部分语法足够长,我懒得格式化这一切,但它在顶级指定 init-declarator-list ,然后声明符,并且(跳过几个级别)下降到cv-qualifier,这是constvolatile。至少通过我的阅读,它基本上允许constvolatile与指定类型的其他内容自由混合。

答案 2 :(得分:0)

嗯,以下是我猜的。我试着解释这个。

static int *ptr1;
int* static ptr2;

第一个意味着它是一个指针,指向一个静态整数。 第二个意味着它是一个静态变量,具有整数指针类型。

我认为另一种方式应该有类似的解释。