简体   繁体   中英

type qualifier without type specifier

In the ISO/IEC 9899:1999, in §6.7.7 Type definitions , the 3rd example (the 6th paragraph marked on the border) is incorrect. The explanation from the example is so (see the code in the bottom):

The first two bit-field declarations differ in that unsigned is a type specifier (which forces t to be the name of a structure member), while const is a type qualifier ( which modifies t which is still visible as a typedef name ).

It states that a declaration const t:5 will make constant a previous definition of the type name t . If we test this using gcc we see that we can mutate such a variable, so gcc ignores const t . The same happens with with a compilation with clang.

I understand that it is possible to exist variables defined/declared via type qualifiers without type specifiers, which was contrary to my belief that a qualifier was only an attribute of a node keeping a type specifier, etc.

Where is the ambiguity in the C99?

typedef signed int t;
typedef int plain;
struct tag {
  unsigned t:4;
  const t:5;
  plain r:5;
};

int
main()
{
  t x;
  x = 10;
  return 0;
}

On the other hand, a function like the next one also compiles:

int
main()
{
  struct tag x = {.t = 3};
  x.t = 4;
  return 0;
}

REMARK :

I used clang and gcc.

DOCUMENTS :

Page 138, §6.7.8 from this edition

ISO/IEC 9899:201x Committee Draft — April 12, 2011 N1570

OR

Page 124, §6.7.7 from this edition

ISO/IEC 9899:TC3 Committee Draft — September 7, 2007 WG14/N1256

The complete spiel for the example (from ISO/IEC 9899:2011) is:

EXAMPLE 3 The following obscure constructions

 typedef signed int t; typedef int plain; struct tag { unsigned t:4; const t:5; plain r:5; }; 

declare a typedef name t with type signed int , a typedef name plain with type int , and a structure with three bit-field members, one named t that contains values in the range [0, 15], an unnamed const-qualified bit-field which (if it could be accessed) would contain values in either the range [−15, +15] or [−16, +15], and one named r that contains values in one of the ranges [0, 31], [−15, +15], or [−16, +15]. (The choice of range is implementation-defined.) The first two bit-field declarations differ in that unsigned is a type specifier (which forces t to be the name of a structure member), while const is a type qualifier (which modifies t which is still visible as a typedef name). If these declarations are followed in an inner scope by

 tf(t (t)); long t; 

then a function f is declared with type ''function returning signed int with one unnamed parameter with type pointer to function returning signed int with one unnamed parameter with type signed int '', and an identifier t with type long int .

Note that the field identified by const t:5; is anonymous and therefore cannot be accessed (the standard mentions that with the 'if it could be accessed' comment, and the statement that it is an 'unnamed const-qualified bit-field'). The field named t is not const-qualified; it can be modified.

And the const field is part of the structure struct tag and does not affect anything outside that structure type.

Both your example programs should compile — it is just as well that GCC and Clang do compile them.

Note, too, that the example is marked 'obscure constructions'. Anyone actually writing code like that for production should be … shunned until they repent of their evil ways.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM