I know the title seems quite stupid, but I think it's worth asking.
Take this declaration(or definition, maybe) for example:
_Thread_local long volatile static int _Atomic const long unsigned x = 10;
I used to consider long long
as a type, but if it's a type name, how can so many qualifiers be inserted into it?
So I consulted N1570 with this question, only to be more confused. It mentions some terms such as "type-specifier" and "type-qualifier", and I can't find long long
in "type specifiers", but isn't long long
a primitive type in C? There are so many books telling me so!
Clarifying not duplicate:
Yes, I saw an existing question deals with long int long
, but this question have something to do with qualifiers, and is in C.
LongLong (LongLong integer) variables are stored as signed 64-bit (8-byte) numbers ranging in value from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. The type-declaration character for LongLong is the caret (^). LongLong is a valid declared type only on 64-bit platforms.
The maximum possible integer input can be taken in C using long long int. It has a range of −9,223,372,036,854,775,807 to +9,223,372,036,854,775,807. If you only deal with positive numbers then unsigned long long can be used which has a range of 0 to 18,446,744,073,709,551,615.
If you read the right bits of the standard carefully enough, you find that the monster declaration in the question is valid, even if implausible.
The 'right bits' includes:
6.2.5 Types
There are five standard signed integer types, designated as
signed char
,short int
,int
,long int
, andlong long int
. (These and other types may be designated in several additional ways, as described in 6.7.2.)…
For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword
unsigned
) that uses the same amount of storage (including sign information) and has the same alignment requirements.6.7.2 Type specifiers
At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name. Each list of type specifiers shall be one of the following multisets (delimited by commas, when there is more than one multiset per item); the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers.
…
long long
,signed long long
,long long int
, orsigned long long int
unsigned long long
, orunsigned long long int
Other declaration specifiers include storage classes (static
and _Thread_local
in the example), and type qualifiers (volatile
and _Atomic
).
6.7 Declarations
6.7 Declarations
Syntax
declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declarationdeclaration-specifiers:
storage-class-specifier
declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
Also, as noted by Olaf in a comment:
6.11.5 Storage-class specifiers
The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.
It is also eccentric to split up the integer type keywords (the type specifier). A more orthodox version of the declaration would be:
static _Thread_local _Atomic const volatile unsigned long long int x = 10;
(or it might drop the int
).
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