Re: Bit-fields and integral promotion
From: Jack Klein (jackklein_at_spamcop.net)
Date: 02/04/05
- Next message: Jack Klein: "Re: Conversion from Unsigned to Signed for bitwise."
- Previous message: Jack Klein: "Re: Creating a message queue with a specific ID"
- In reply to: CBFalconer: "Re: Bit-fields and integral promotion"
- Next in thread: CBFalconer: "Re: Bit-fields and integral promotion"
- Reply: CBFalconer: "Re: Bit-fields and integral promotion"
- Reply: Tim Rentsch: "Re: Bit-fields and integral promotion"
- Reply: Keith Thompson: "Re: Bit-fields and integral promotion"
- Reply: lawrence.jones_at_ugs.com: "Re: Bit-fields and integral promotion"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Thu, 03 Feb 2005 23:40:26 -0600
On Wed, 02 Feb 2005 09:52:40 GMT, CBFalconer <cbfalconer@yahoo.com>
wrote in comp.std.c:
> Alex Fraser wrote:
> > "CBFalconer" <cbfalconer@yahoo.com> wrote in message
> >> lawrence.jones@ugs.com wrote:
> >>> In comp.std.c CBFalconer <cbfalconer@yahoo.com> wrote:
> >>>>
> >>>> It would suffice to say that any bitfield is treated as having
> >>>> the specified type for any further operations.
> >>>
> >>> It would also be completely wrong. See DR 122:
> >>>
> >>> <http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_122.html>
> >>
> >> As you may have gathered from my previous postings, I am deeply
> >> opposed to that. It obviously isn't officially incorporated into
> >> the standard, and doing so would be a mistake.
> >
> > The standard very clearly intends to specify the behaviour.
> > Unfortunately, not in a completely unambiguous manner - hence
> > the defect report.
>
> Of course it should enforce a behavior. However that behavior
> should be both rational and agree with existing practice. It seems
> that existing practice already varies.
>
> >
> > The wording of the standard is easily understood for types subject
> > to integer promotion other than bit-fields, and defines different
> > behaviour to what you suggest should apply to bit-fields. I believe
> > the intention was for the two to be consistent - bit-fields should
> > be viewed as a "small" type like unsigned char and unsigned short -
> > and this agrees with the response to the defect report.
>
> Others, and I, have pointed out the anomalies that can result from
> this attitude. The opportunity should be taken to clean this up
> without contravening any earlier standard. C is already a morass
> of insecurities, there is no need to add another.
Personally I would have preferred the choice of "sign preserving"
promotions over the "value preserving" that was selected by the
committee. Apparently there were pre-standard implementations that
promoted unsigned char to signed int, although I can't remember ever
using one in the K&R days.
> One ridiculous result of this attitude is that a 1 bit field,
> whether declared as int or unsigned int, would always be treated as
> -1 or 0. This is contrary to the usual C practice. The
> opportunity exists to ensure that booleans stored in bit fields are
> properly expanded. Or should we have to write !!x for any boolean
> x stored in a bitfield?
The ridiculous thing about the paragraph above is your conclusion, as
I'm sure you'd realize if you rethink it carefully.
A signed int 1 bit field can indeed only contain the values 0 and -1.
An unsigned int 1 bit field can only contain the values 0 and 1. If
it contains the value 1, it will promote to a signed int with the
value 1. How can you possible maintain that it promotes to -1 in a
signed int? Perhaps you are thinking of how you would write assembly
language for some particular processor, but that has nothing to do
with preserving the value.
C conversions, and integral promotions, are always about the value,
not about the bit pattern.
Given the fact that "value preserving" has been the language standard
for a decade and a half, it is far more important that unsigned bit
fields promote exactly the same way is lesser rank integer types of
the same with and range of values.
Assume one of today's most common desk top platform with 8-bit chars,
16-bit shorts, and 32-bit ints. Now consider:
#include <stdio.h>
struct nu
{
unsigned uc: 8;
unsigned us: 16;
};
int main(void)
{
unsigned char uc = 0;
unsigned short us = 0;
struct nu nu = { 0, 0 };
if ((uc - 5) < 0)
puts("unsigned char promotes to signed");
else
puts("unsigned char promotes to unsigned");
if ((nu.uc - 5) < 0)
puts("unsigned :8 promotes to signed");
else
puts("unsigned :8 promotes to unsigned");
if ((us - 5) < 0)
puts("unsigned short promotes to signed");
else
puts("unsigned short promotes to unsigned");
if ((nu.us - 5) < 0)
puts("unsigned :16 promotes to signed");
else
puts("unsigned :16 promotes to unsigned");
return 0;
}
Under your interpretation, the results are different for the 8-bit
unsigned bit-field and the 8-bit unsigned char, and also different for
the 16-bit unsigned bit-field and the 16-bit unsigned short.
Amazingly, I just tested this with four compilers, all of which got it
wrong.
But the standard does specifically say you are wrong:
6.7.2.1 Structure and union specifiers P9:
"A bit-field is interpreted as a signed or unsigned integer type
consisting of the specified number of bits."
So the type of an unsigned int bit field is NOT unsigned int, it is a
(perhaps unnamed type) uintn_t, where 'n' is the width in bits.
And:
6.3.1.1 Boolean, characters, and integers P1
"The rank of a signed integer type shall be greater than the rank of
any signed integer type with less precision."
[snip]
"The rank of any unsigned integer type shall equal the rank of the
corresponding signed integer type, if any."
And finally:
6.3.1.2 P2
"If an int can represent all values of the original type, the value is
converted to an int; otherwise, it is converted to an unsigned int."
The first quote makes it clear that the type of an 'n' bit unsigned
integer bit-field is "n-bit unsigned integer type". By the definition
of all unsigned integer types, it has a precision of n-bits.
If n is less than the number of value bits in a signed int, it is
quite clear that this "n-bit unsigned integer type" has a lesser rank
than type int. This means it is subjected to the "integer
promotions".
And since an int can hold all the values of this type, it must be
promoted to int, not unsigned int.
While these quotations are copied and pasted from a copy of C99, C90
contained the same.
"The opportunity should be taken to clean this up without contravening
any earlier standard." is not possible.
-- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
- Next message: Jack Klein: "Re: Conversion from Unsigned to Signed for bitwise."
- Previous message: Jack Klein: "Re: Creating a message queue with a specific ID"
- In reply to: CBFalconer: "Re: Bit-fields and integral promotion"
- Next in thread: CBFalconer: "Re: Bit-fields and integral promotion"
- Reply: CBFalconer: "Re: Bit-fields and integral promotion"
- Reply: Tim Rentsch: "Re: Bit-fields and integral promotion"
- Reply: Keith Thompson: "Re: Bit-fields and integral promotion"
- Reply: lawrence.jones_at_ugs.com: "Re: Bit-fields and integral promotion"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|