Static and volatile qualifiers after type
Bjarne explains why const can come 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" (originally called "readonly" and had a corresponding "writeonly"), I allowed it to go before or after because I could do it without ambiguity.
My immediate thought was, "Okay, that makes sense, but if that's the reason, then why is const special?" Apparently this is not the case. Both clang and gcc do not issue any warnings about the following.
int volatile myint;
int static myotherint;
It makes sense that it would be valid, but I've never seen this syntax used or even mentioned as a possibility. Puts static and volatile qualifiers after a valid C ++ type?
How to determine this from the text of the standard?
source to share
These parts are actually quite broadly separated in the standard. static
- storage class as specified in clause 7.1.1 / 1:
storage-class-specifier:
register
static
thread_local
extern
mutable
This is used in the 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 it allows you to either static int
or int static
specify the type. Likewise, you can declare a friend function as friend int f();
or int friend f();
.
const
or volatile
can only participate if 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 points the init-declarator list to top level, then the declarator and (skipping multiple levels) is reset to cv-qualifier
which is either const
or volatile
. At least from my reading, it basically allows const
or is volatile
free to mix with other things that type indicates.
source to share
Yes, this syntax is fine. The first part of the grammar of the declaration is a sequence of decl specifiers. These include settings for storage class specifiers types, functions friend
, typedef
and constexpr
. The grammar allows them to appear in any order. However, the semantic rules introduced on them introduce some restrictions. For example, a variable declaration must always have one type specifier that is not a cv qualifier ( const
or volatile
). Also, there must not be more than one storage class specifier (except thread_local
may appear with static
or extern
).
Note that the sequence of declaration specifiers appears before any composite type syntax, such as pointers, references, arrays, etc. For example, the decl specifier sequence is noted in the following examples:
static const int *p;
| |
char volatile static *(&p)[20];
| |
Note that volatile
is a cv classifier like const
, so the reasons to allow volatile
in the example you give are the same as for const
. These keywords can also appear deeper in the declaration (as in int *volatile x;
).
By convention, we write the storage class first, then follow the type hints and cv qualifiers where appropriate. I prefer to write my CV qualifications after the type specifiers they correspond to as they are more consistent.
You might want to read What are declarations and declarators and how are their types interpreted by the standard? ...
source to share
Well, that's what I think. I am trying to interpret this.
static int *ptr1;
int* static ptr2;
the former means that it is a pointer pointing to a static integer. the second means that it is a static variable with an integer pointer type.
I think the other way should have a similar intuition.
source to share