For example, let's consider the static
storage class specifier. Here are a few examples of both valid and ill-formed uses of this storage class specifier:
static int a; // valid int static b; // valid static int* c; // valid int static* d; // valid int* static e; // ill-formed static int const* f; // valid int static const* g; // valid int const static* h; // valid int const* static i; // ill-formed typedef int* pointer; static pointer j; // valid pointer static k; // valid
(The declarations marked "valid" were accepted by Visual C++ 2012, g++ 4.7.2, and Clang++ 3.1. The declarations marked "ill-formed" were rejected by all of those compilers.)
This seems odd because the storage class specifier applies to the declared variable. It is the declared variable that is static
, not the type of the declared variable. Why are e
and i
ill-formed, but k
is well-formed?
What are the rules that govern valid placement of storage class specifiers? While I've used static
in this example, the question applies to all storage class specifiers. Preferably, a complete answer should cite relevant sections of the C++11 language standard and explain them.
The four storage classes in C are declared in a block or program with the storage class specifiers, auto, register, extern, static. There is one more storage class specifier, 'typedef' used in the syntactic form, and does not reserve storage.
A storage class specifier is used to refine the declaration of a variable, a function, and parameters. Storage classes determine whether: The object has internal, external, or no linkage. The object is to be stored in memory or in a register, if available.
The code below shows the declaration of storage class specifiers in C: The auto variable a is defined and printed in the main function. The register variable b is defined and printed in the test_func . The extern variable c is defined outside the functions and printed in the main function.
In summary, anywhere in the declaration specifier (See section 7.1 in the ISO/IEC 14882-2012), ie before the *
. Qualifiers after the *
are associated with the pointer declarator, not the type specifier, and static
doesn't make sense within the context of a pointer declarator.
Consider the following cases: You can declare a normal int and a pointer to an int in the same declaration list, like this:
int a, *b;
this is because the type specifier is int
, then you have two declarations using that type specifier int
, a
, and a pointer declarator *a
which declares a pointer to int
. Now consider:
int a, static b; // error int a, *static b; // error int a, static *b; // error
which should look wrong (as they are), and the reason (as defined in sections 7.1 and 8.1) is because C and C++ require that your storage specifiers go with your type specifier, not in your declarator. So now it should be clear that that the following is also wrong, since the above three are also wrong:
int *static a; // error
Your last example,
typedef int* pointer; static pointer j; // valid pointer static k; // valid
are both valid and both equivalent because the pointer
type is defined as a type specifier and you can put your type specifier and storage specifeir in any order. Note that they are both equivalent and would be equivalent to saying
static int *j; static int *k;
or
int static *j; int static *k;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With