类型后的静态和volatile限定符

static and volatile qualifiers after type

本文关键字:volatile 静态 类型      更新时间:2023-10-16

Bjarne解释了为什么const可以放在类型的前面或后面。

http://www.stroustrup.com/bs_faq2.html constplacement

"const T" and "T const" were - and are - (both) allowed and equivalent.
[...]

为什么?当我发明"const"(最初命名为"readonly")并拥有一个对应的"只写"),我允许它在之前或之后,因为这样做不会产生歧义。

我的第一个想法是,"好吧,这有道理,但如果这就是原因,那么为什么const是特殊的?"显然不是。clang和gcc都不会对以下命令发出警告。
int volatile myint;
int static myotherint;

这是有意义的,这将是有效的,但我从未见过这种语法被使用,甚至被提及作为一种可能性。在类型之后放置静态和volatile限定符是否有效?

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

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

请注意,decl-specifier序列出现在任何复合类型语法(如指针、引用、数组等)之前。例如,在以下示例中标记了decl说明符的序列:

static const int *p;
|              |
char volatile static *(&p)[20];
|                  |

注意volatileconst一样是cv限定符,所以在你给出的例子中允许volatile的原因和const是一样的。这些关键字也可以出现在声明的更深处(如int *volatile x;)。

按照惯例,我们先写存储类指定,然后写类型指定和cv-限定符。我更喜欢把我的cv-qualifications 写在对应的类型说明符之后,因为这样更一致。

你可能想读一下什么是声明和声明符以及它们的类型是如何被标准解释的

这些部分在标准中实际上是相当分散的。static是一个存储类,如§7.1.1/1:

所述
storage-class-specifier:
    register
    static
    thread_local
    extern
    mutable

decl说明符中使用,如§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,然后是declarator,然后(跳过几个级别)到达cv-qualifier,即constvolatile。至少在我的阅读中,它基本上允许constvolatile与指定类型的其他东西自由混合。

好吧,下面是我的猜测。我试着解释一下。

static int *ptr1;
int* static ptr2;

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

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