static and volatile qualifiers after type
Asked Answered
K

3

5

Bjarne explains why const can go either before or after a type.

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

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

Why? When I invented "const" (initially named "readonly" and had a corresponding "writeonly"), I allowed it to go before or after the type because I could do so without ambiguity.

My immediate thought was, "Ok, that makes sense, but if that's the reason then why is const special?" Apparently it isn't. Both clang and gcc emit no warnings for the following.

int volatile myint;
int static myotherint;

It makes sense that this would be valid but I've never seen this syntax used or even mentioned as a possibility. Is placing static and volatile qualifiers after a type valid C++?

How would one determine this from the text of the Standard?

Knighthood answered 20/8, 2014 at 22:54 Comment(0)
I
2

These pieces are actually rather widely separated in the standard. static is a storage class, as specified in §7.1.1/1:

storage-class-specifier:
    register
    static
    thread_local
    extern
    mutable

That's used in a decl-specifier, as defined in §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

So, this allows either static int or int static to specify a type. Likewise, you could declare a friend function as either friend int f(); or int friend f();.

const or volatile can only get involved when you actually declare something, so it falls under "declarators" in § 8. This part of the grammar is long enough I'm too lazy to format it all, but it specifies init-declarator-list at the top level, then declarator, and (skipping a few levels) gets down to cv-qualifier which is either const or volatile. At least by my reading, it basically allows the const or volatile to be freely intermixed with the other things that specify a type.

Inexorable answered 20/8, 2014 at 23:23 Comment(0)
L
5

Yes, that syntax is fine. The first part of the declaration grammar is a sequence of decl-specifiers. These include storage class specifies, type specifiers, function specifies, friend, typedef, and constexpr. The grammar allows them to appear in any order. However, the semantic rules placed on them introduce some restrictions. For example, in a variable declaration there must always be one type specifier that is not a cv-qualifier (const or volatile). There also must never be more than one storage class specifier (except thread_local can appear with static or extern).

Note that the sequence of decl-specifiers comes before any compound type syntax, such as pointers, references, arrays, and so on. For example, the sequence of decl-specifiers is marked in the following examples:

static const int *p;
|              |

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

Note that volatile is a cv-qualifier like const, so the reasons for allowing volatile in the example you gave are the same as for const. These keywords can also appear deeper within the declaration (as in int *volatile x;).

By convention, we write storage class specifies first, followed by type specifies and cv-qualifiers where appropriate. I prefer to write my cv-qualifications after the type specifiers to which they correspond, as it is more consistent.

You may want to have a read of What are declarations and declarators and how are their types interpreted by the standard?.

Lupus answered 20/8, 2014 at 23:9 Comment(0)
I
2

These pieces are actually rather widely separated in the standard. static is a storage class, as specified in §7.1.1/1:

storage-class-specifier:
    register
    static
    thread_local
    extern
    mutable

That's used in a decl-specifier, as defined in §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

So, this allows either static int or int static to specify a type. Likewise, you could declare a friend function as either friend int f(); or int friend f();.

const or volatile can only get involved when you actually declare something, so it falls under "declarators" in § 8. This part of the grammar is long enough I'm too lazy to format it all, but it specifies init-declarator-list at the top level, then declarator, and (skipping a few levels) gets down to cv-qualifier which is either const or volatile. At least by my reading, it basically allows the const or volatile to be freely intermixed with the other things that specify a type.

Inexorable answered 20/8, 2014 at 23:23 Comment(0)
N
0

well, following is what i guess. i try to interpret this.

static int *ptr1;
int* static ptr2;

first one means it's a pointer, pointing to a static integer. second one means that that it's a static variable, with type of integer pointer.

i think the other way should has the similar intepretation.

Nilsson answered 20/8, 2014 at 23:3 Comment(4)
int* static ptr2; is not a valid declaration.Lupus
@JosephMansfield you tested it? would int static *ptr3; work?Nilsson
@HuStmpHrrrr That one is fine.Lupus
@JosephMansfield yeah, it looks like a static pointer pointing to an integer.Nilsson

© 2022 - 2024 — McMap. All rights reserved.