Topic: Bit-field specification incomplete?


Author: sdouglas@armltd.co.uk (scott douglass)
Date: 1996/03/19
Raw View
Hello,

I was surprised to find that section 9.6, Bit-fields, does not prohibit
'struct T { int i:-1; };' or 'struct T { int i:0; };' which are constraint
violations in the C standard.  It also does not explicitly state that the
member must act as an integer of the specified numbers of bits.  As it
stands I think a compiler can ignore the width specification entirely
except that it must prevent the address of the field from being taken and
prevent references to the field.  [I'm assuming the phrase "shall not"
means a program that tries to do so is ill-formed.]

Should this be fixed?

[The rest of this seems pretty archane, even to me but it seems like the
answers should be in the standard.]

Since the draft says nothing specifically about the type of a bit-field
member, I assume that it is the type of the member ignoring the bit-field
specifier.  [Although in section 7.2,  Enumeration declarations, it says
"The underlying type of an enumeration shall not be a bitfield." implying
that there is such a thing as a bit-field type.]  So given,

enum E { k0, k1, k2 };
struct T { bool b:2; char c:2; short s:2; int i:2; long l:2; E e:2; };

void g(bool);
void g(char); void g(unsigned char); void g(signed char);
void g(short); void g(unsigned short);
void g(int); void g(unsigned int);
void g(long); void g(unsigned long);
void g(E);

void f(const T* t)
   {
   g(t->b);  // calls g(bool);
   g(t->c);  // calls g(char);
   g(t->s);  // calls g(short);
   g(t->i);  // calls g(int);
   g(t->l);  // calls g(long);
   g(t->e);  // calls g(E);
   }

[And so on for 'unsigned char', 'signed char', 'wchar_t', 'unsigned
short', 'short', 'unsigned int' and 'unsigned long'.]

Is this correct?  Or does the type of a bit-field depend on the
implementation-defined signedness of bit-fields?  If so, then on an
unsigned plain bit-field machine I would imagine the type of 't->i' above
would be 'unsigned int' but what is the type of 't->c' -- 'char' or
'unsigned char'?

[Are there 'unsigned wchar_t' or 'signed wchar_t'?  I don't think so, but,
section 3.9.1, Fundamental Types, does not explicitly prohibit them as it
does for 'bool' and does not explicitly allow them as it does for 'char'.]

Finally, the promotion of a bit-field is specified in 4.5, Integral
promotions.  It specifies that all non-enum bit-fields promote to 'int' or
'unsigned int'.  This seems wrong for 'long' and 'unsigned long'
bit-fields.  Why should they "promote" to 'int' or 'unsigned int'?  I
would expect a bit-field of type 'long' to have type 'long' or 'unsigned
long' even if the width is short enough to fit in an 'int'.  After all, a
bit-field of enum type where the enum range is too big for 'unsigned int'
promotes to 'long' or 'unsigned long' even if the width is short enough to
fit in an 'int'.

Thanks,
    --scott
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1996/03/19
Raw View
In article 1903961604090001@193.131.176.202, sdouglas@armltd.co.uk (scott douglass) writes:
>
>I was surprised to find that section 9.6, Bit-fields, does not prohibit
>'struct T { int i:-1; };' or 'struct T { int i:0; };' which are constraint
>violations in the C standard.

That looks to me like an oversight in the draft.

>  It also does not explicitly state that the
>member must act as an integer of the specified numbers of bits.

I believe that is deliberate. The actual amount of space allocated is
implementation-dependent, as long as it is at least the amount specified.
If you specify a "long" member bitfield of 8 bits, the actual behavior will
be implementation-dependent. If you specify a bitfield wider than the
type, there is no portable way to determine what happens to the extra bits.
Example: Suppose type short is 16 bits, and you write
 short data : 24;
You can expect to store any short value in the bitfield and get that
value back when you read the bitfield. Anything beyond that, including
what happens if you increment "data" beyond SHORT_MAX, depends on
the implementation. (Some of these points were discussed at the C++ Committee
meeting last week, and it was decided not to specify the behavior. The
reason is that so much depends on the implementation already that there
isn't much the standard could usefully say.)

>Since the draft says nothing specifically about the type of a bit-field
>member, I assume that it is the type of the member ignoring the bit-field
>specifier.

That is correct. The bitfield specification is a request to the compiler to
perform some implementation-dependent packing of the data. The type of the
member is the declared type. (Use a too-short bitfield at your own risk.)

>Finally, the promotion of a bit-field is specified in 4.5, Integral
>promotions.  It specifies that all non-enum bit-fields promote to 'int' or
>'unsigned int'.  This seems wrong for 'long' and 'unsigned long'
>bit-fields.

That has already been fixed. The current draft says promotion occurs only
if type int (or unsigned int) can represent all the values of the bitfield.
If the bitfield is larger, no promotion occurs.

---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]