Topic: bit-fields and integral promotions
Author: Ben Hutchings <ben-public-nospam@decadentplace.org.uk>
Date: Tue, 6 Feb 2007 21:39:18 CST Raw View
On 2007-02-06, Dave Thompson <david.thompson1@worldnet.att.net> wrote:
> On Sun, 21 Jan 2007 23:16:16 CST, Ben Hutchings
><ben-public-nospam@decadentplace.org.uk> wrote:
><snip>
>> > (The text in 9.6 seems to imply just the opposite, that 1)
>> > explicitly signed or unsigned types must behave as the declared
>> > type, and 2) types like int, etc. may behave as either signed or
>> > unsigned.)
>>
>> I read that as meaning that whereas int etc. are normally treated as
>> shorthand for signed int etc. the interpretation can be different in
>> case of a bit-field member declaration. This is presumably done for
>> compatibility with C90, which doesn't require any support for signed
>> bit-fields at all if I remember correctly.
>>
> C90 (and C99) and C++ require support for both signed and unsigned
> bitfields, but let the implementation choose which 'plain' int is,
> unlike 'full-size' variables where all 'plain' integer types except
> char are (aka default to) signed.
<snip>
Evidently this limitation was corrected earlier than I remembered.
It was documented in K&R first edition that the default signed-ness
of bit-fields is implementation-defined; yet there was no "signed"
keyword to override this.
Ben.
--
Ben Hutchings
We get into the habit of living before acquiring the habit of thinking.
- Albert Camus
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Asif Lodhi" <asif.lodhi@gmail.com>
Date: Mon, 29 Jan 2007 10:21:03 CST Raw View
Hi,
On 12 Jan, 03:25, r...@sei.cmu.edu (Robert Seacord) wrote:
> ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
> [ISO/IEC 14882-2003] says:
>
> An rvalue for an integral bit-field (9.6) can be converted to an rvalue
> of type int if int can represent all the values of the bit-field;
> otherwise, it can be converted to unsigned int if unsigned int can
> represent all the values of the bit-field.
>
> In the following example:
>
> struct {
> unsigned int a: 8;
>
> } bits = {255};int main() {
> cout << "unsigned 8-bit field promotes to"
> << (bits.a << 24) < 0 ? "signed" : "unsigned"
> << endl;
>
> }The type of the expression (bits.a << 24) should be int for a (typical)
> architecture where int is represented by a 32-bit (or even a 16-bit)
> value. However, most implementations including Microsoft Visual Studio
> 7.1 and g++ version 4.1.0 promote (bits.a << 24) to unsigned int.
>
> Do I misunderstand, or is this some sort of weird conspiracy? 8^)
The section "C.6.1 Promotions", of "The C++ Programming Language" by
Bjarne Stroustrup, says "A bit-field is converted to an int if int can
represent all the values of the bit-field; otherwise, it is converted
to unsigned int if unsigned int can represent all the values of the
bit-filed. Otherwise, no integral promotions applies to it."
HTH
--
Asif
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Asif Lodhi" <asif.lodhi@gmail.com>
Date: Mon, 29 Jan 2007 10:21:32 CST Raw View
Hi,
Adding to my earlier post, the result of your shift still falls within
a 32-bit unsigned int range so the result is unsigned.
--
Asif
On 12 Jan, 03:25, r...@sei.cmu.edu (Robert Seacord) wrote:
> ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
> [ISO/IEC 14882-2003] says:
>
> An rvalue for an integral bit-field (9.6) can be converted to an rvalue
> of type int if int can represent all the values of the bit-field;
> otherwise, it can be converted to unsigned int if unsigned int can
> represent all the values of the bit-field.
>
> In the following example:
>
> struct {
> unsigned int a: 8;
>
> } bits = {255};int main() {
> cout << "unsigned 8-bit field promotes to"
> << (bits.a << 24) < 0 ? "signed" : "unsigned"
> << endl;
>
> }The type of the expression (bits.a << 24) should be int for a (typical)
> architecture where int is represented by a 32-bit (or even a 16-bit)
> value. However, most implementations including Microsoft Visual Studio
> 7.1 and g++ version 4.1.0 promote (bits.a << 24) to unsigned int.
>
> Do I misunderstand, or is this some sort of weird conspiracy? 8^)
>
> rCs
>
> ---
> [ comp.std.c++ is moderated. To submit articles, try just posting with ]
> [ your news-reader. If that fails, use mailto:std-...@ncar.ucar.edu ]
> [ --- Please see the FAQ before posting. --- ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html ]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Dave Thompson <david.thompson1@worldnet.att.net>
Date: Tue, 6 Feb 2007 09:46:00 CST Raw View
On Sun, 21 Jan 2007 23:16:16 CST, Ben Hutchings
<ben-public-nospam@decadentplace.org.uk> wrote:
<snip>
> > (The text in 9.6 seems to imply just the opposite, that 1)
> > explicitly signed or unsigned types must behave as the declared
> > type, and 2) types like int, etc. may behave as either signed or
> > unsigned.)
>
> I read that as meaning that whereas int etc. are normally treated as
> shorthand for signed int etc. the interpretation can be different in
> case of a bit-field member declaration. This is presumably done for
> compatibility with C90, which doesn't require any support for signed
> bit-fields at all if I remember correctly.
>
C90 (and C99) and C++ require support for both signed and unsigned
bitfields, but let the implementation choose which 'plain' int is,
unlike 'full-size' variables where all 'plain' integer types except
char are (aka default to) signed.
But, C++ allows all integer and enum types, while C90 allows only
[signed|unsigned] int and C99 also allows _Bool and more at the
implentation's choice; and C++ allows the number-bits to exceed the
width of the declared type (leaving the extra as padding) while C
makes this a constraint violation.
- David.Thompson1 at worldnet.att.net
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Ben Hutchings <ben-public-nospam@decadentplace.org.uk>
Date: Sun, 21 Jan 2007 23:16:16 CST Raw View
On 2007-01-12, James Kanze <james.kanze@gmail.com> wrote:
> Greg Herlihy wrote:
<snip>
>> The value obtained from left-shifting an unsigned type is unsigned.
>> Therefore, since bits.a is unsigned, bits.a << 24 is unsigned as well.
>
> What is shifted is the results of the integral promotion of
> bits.a. The text he quoted does seem to suggest that this is an
> int, although I don't think that that is the intention.
I'm tempted to ask what "rvalue for an integral bit-field" is intended
to mean. I can't see any justification for the idea that an rvalue can
have some kind of bit-field nature. It's explicitly not part of the
type of a bit-field member, so there's no reason to expect it to be
retained by lvalue-to-rvalue conversion.
If some special rule is intended, perhaps it should be part of the
lvalue-to-rvalue conversion and not the integral promotions. But I
think that this rule is redundant and can be deleted.
> (The text in 9.6 seems to imply just the opposite, that 1)
> explicitly signed or unsigned types must behave as the declared
> type, and 2) types like int, etc. may behave as either signed or
> unsigned.)
I read that as meaning that whereas int etc. are normally treated as
shorthand for signed int etc. the interpretation can be different in
case of a bit-field member declaration. This is presumably done for
compatibility with C90, which doesn't require any support for signed
bit-fields at all if I remember correctly.
Ben.
--
Ben Hutchings
Reality is just a crutch for people who can't handle science fiction.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Thu, 11 Jan 2007 17:56:20 CST Raw View
Robert Seacord wrote:
> ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
> [ISO/IEC 14882-2003] says:
>
> An rvalue for an integral bit-field (9.6) can be converted to an rvalue
> of type int if int can represent all the values of the bit-field;
> otherwise, it can be converted to unsigned int if unsigned int can
> represent all the values of the bit-field.
>
> In the following example:
>
> struct {
> unsigned int a: 8;
> } bits = {255};
>
> int main() {
> cout << "unsigned 8-bit field promotes to"
> << (bits.a << 24) < 0 ? "signed" : "unsigned"
> << endl;
> }
>
> The type of the expression (bits.a << 24) should be int for a (typical)
> architecture where int is represented by a 32-bit (or even a 16-bit)
> value. However, most implementations including Microsoft Visual Studio
> 7.1 and g++ version 4.1.0 promote (bits.a << 24) to unsigned int.
>
> Do I misunderstand, or is this some sort of weird conspiracy? 8^)
The value obtained from left-shifting an unsigned type is unsigned.
Therefore, since bits.a is unsigned, bits.a << 24 is unsigned as well.
There is no conversion from a bit-field to an int in the sample
program, so the rules concerning integral promotions do no apply.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Jack Klein <jackklein@spamcop.net>
Date: Fri, 12 Jan 2007 09:49:33 CST Raw View
On Thu, 11 Jan 2007 17:56:20 CST, "Greg Herlihy" <greghe@pacbell.net>
wrote in comp.std.c++:
>
> Robert Seacord wrote:
> > ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
> > [ISO/IEC 14882-2003] says:
> >
> > An rvalue for an integral bit-field (9.6) can be converted to an rvalue
> > of type int if int can represent all the values of the bit-field;
> > otherwise, it can be converted to unsigned int if unsigned int can
> > represent all the values of the bit-field.
> >
> > In the following example:
> >
> > struct {
> > unsigned int a: 8;
> > } bits = {255};
> >
> > int main() {
> > cout << "unsigned 8-bit field promotes to"
> > << (bits.a << 24) < 0 ? "signed" : "unsigned"
> > << endl;
> > }
> >
> > The type of the expression (bits.a << 24) should be int for a (typical)
> > architecture where int is represented by a 32-bit (or even a 16-bit)
> > value. However, most implementations including Microsoft Visual Studio
> > 7.1 and g++ version 4.1.0 promote (bits.a << 24) to unsigned int.
> >
> > Do I misunderstand, or is this some sort of weird conspiracy? 8^)
>
> The value obtained from left-shifting an unsigned type is unsigned.
> Therefore, since bits.a is unsigned, bits.a << 24 is unsigned as well.
> There is no conversion from a bit-field to an int in the sample
> program, so the rules concerning integral promotions do no apply.
This is quite wrong. 5.8 Shift operators specifically states "The
operands shall be of integral or enumeration type and integral
promotions are performed. The type of the result is that of the
promoted left operand."
So an 8-bit bit-field is promoted to either int or unsigned int before
the shift, and that signed/unsigned int is then shifted, with the
result having the type of the promoted bit-field.
This happens to be something that most C and C++ compilers seem to do
incorrectly, either accidentally or deliberately. All the ones that I
have actually checked promote unsigned bit-fields to unsigned int,
even when it should, under the standard, be promoted to signed int.
I do not know if they are ignoring this aspect of both language
standards deliberately, perhaps for compatibility with pre-standard
implementations, or through simple misunderstanding.
Does anyone know which is the reason? Any compiler implementers have
an answer for their implementation?
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
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
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "James Kanze" <james.kanze@gmail.com>
Date: Fri, 12 Jan 2007 10:28:14 CST Raw View
Greg Herlihy wrote:
> Robert Seacord wrote:
> > ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
> > [ISO/IEC 14882-2003] says:
> > An rvalue for an integral bit-field (9.6) can be converted to an rvalue
> > of type int if int can represent all the values of the bit-field;
> > otherwise, it can be converted to unsigned int if unsigned int can
> > represent all the values of the bit-field.
> > In the following example:
> > struct {
> > unsigned int a: 8;
> > } bits = {255};
> > int main() {
> > cout << "unsigned 8-bit field promotes to"
> > << (bits.a << 24) < 0 ? "signed" : "unsigned"
> > << endl;
> > }
> > The type of the expression (bits.a << 24) should be int for a (typical)
> > architecture where int is represented by a 32-bit (or even a 16-bit)
> > value. However, most implementations including Microsoft Visual Studio
> > 7.1 and g++ version 4.1.0 promote (bits.a << 24) to unsigned int.
> > Do I misunderstand, or is this some sort of weird conspiracy? 8^)
> The value obtained from left-shifting an unsigned type is unsigned.
> Therefore, since bits.a is unsigned, bits.a << 24 is unsigned as well.
What is shifted is the results of the integral promotion of
bits.a. The text he quoted does seem to suggest that this is an
int, although I don't think that that is the intention. (The
text in 9.6 seems to imply just the opposite, that 1)
explicitly signed or unsigned types must behave as the declared
type, and 2) types like int, etc. may behave as either signed or
unsigned.)
> There is no conversion from a bit-field to an int in the sample
> program, so the rules concerning integral promotions do no apply.
Are you saying that promotion doesn't take place? (The rules
for promotion can be pretty wierd: shifting an unsigned char
left 24 on a 32 bit machine can result in a negative value.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Fri, 12 Jan 2007 12:01:56 CST Raw View
Jack Klein wrote:
> On Thu, 11 Jan 2007 17:56:20 CST, "Greg Herlihy" <greghe@pacbell.net>
> wrote in comp.std.c++:
> > Robert Seacord wrote:
> > > ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
> > > [ISO/IEC 14882-2003] says:
> > >
> > > An rvalue for an integral bit-field (9.6) can be converted to an rvalue
> > > of type int if int can represent all the values of the bit-field;
> > > otherwise, it can be converted to unsigned int if unsigned int can
> > > represent all the values of the bit-field.
> > >
> > > In the following example:
> > >
> > > struct {
> > > unsigned int a: 8;
> > > } bits = {255};
> > >
> > > int main() {
> > > cout << "unsigned 8-bit field promotes to"
> > > << (bits.a << 24) < 0 ? "signed" : "unsigned"
> > > << endl;
> > > }
> > >
> > The value obtained from left-shifting an unsigned type is unsigned.
> > Therefore, since bits.a is unsigned, bits.a << 24 is unsigned as well.
> > There is no conversion from a bit-field to an int in the sample
> > program, so the rules concerning integral promotions do no apply.
>
> This is quite wrong. 5.8 Shift operators specifically states "The
> operands shall be of integral or enumeration type and integral
> promotions are performed. The type of the result is that of the
> promoted left operand."
The operand is of the left operand is an unsigned int. After all: "The
bit-field attribute is not part of the type of the class member." So
no integral promotion is needed and none takes place.
> So an 8-bit bit-field is promoted to either int or unsigned int before
> the shift, and that signed/unsigned int is then shifted, with the
> result having the type of the promoted bit-field.
Then what difference did the "unsigned" qualifier make in this
declaration? What was the programmer expecting? That it have no effect?
Why would anyone expect this result to differ from this expression:
255U << 24;
> This happens to be something that most C and C++ compilers seem to do
> incorrectly, either accidentally or deliberately. All the ones that I
> have actually checked promote unsigned bit-fields to unsigned int,
> even when it should, under the standard, be promoted to signed int.
It seems an odd coincidence that every compiler misunderstood what the
Standard states in the same way.
> I do not know if they are ignoring this aspect of both language
> standards deliberately, perhaps for compatibility with pre-standard
> implementations, or through simple misunderstanding.
Even if they came by the interpretation you describe, it doesn't make
much sense. so they probably figure that it could not correct or at any
very useful.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Fri, 12 Jan 2007 15:26:26 CST Raw View
James Kanze wrote:
> Greg Herlihy wrote:
> > Robert Seacord wrote:
> > > In the following example:
>
> > > struct {
> > > unsigned int a: 8;
> > > } bits = {255};
>
> > > int main() {
> > > cout << "unsigned 8-bit field promotes to"
> > > << (bits.a << 24) < 0 ? "signed" : "unsigned"
> > > << endl;
> > > }
> Are you saying that promotion doesn't take place? (The rules
> for promotion can be pretty wierd: shifting an unsigned char
> left 24 on a 32 bit machine can result in a negative value.)
Yes, and Visual C++ and gcc both agree that a's type is "unsigned int."
After all, if the type were not unsigned int, then what other type
could it be?
Furthemore, a simple test with the same two compilers confirms this
explanation:
struct bits
{
unsigned short a : 8;
};
Now bit shifting bits.a like this:
bits b;
b.a = 255;
b.a << 24; // signed
results in a signed value type. The difference here is that the
unsigned short type is eligible for integral promotion, so integral
promotion does take place.
If the Standard wants some other behavior to be "correct", then it will
have to be amended just what that behavior should be exactly.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "rCs" <rcs@cert.org>
Date: Sun, 14 Jan 2007 23:59:49 CST Raw View
Greg Herlihy wrote:
> Yes, and Visual C++ and gcc both agree that a's type is "unsigned int."
> After all, if the type were not unsigned int, then what other type
> could it be?
it could be signed. for example, take the following longer example:
struct {
unsigned int a: 8;
} bits = {255};
struct {
unsigned char a;
} bytes = {255};
unsigned char a = 255;
//#if CHARFIELD
struct {
unsigned char a:8;
} charfield = {255};
//#endif
int main(void) {
printf(LANG ", unsigned 8-bit field promotes to %s.\n",
(bits.a << 24) < 0 ? "signed" : "unsigned");
// C++, unsigned 8-bit field promotes to unsigned.
printf(LANG ", unsigned 8-bit byte promotes to %s.\n",
(bytes.a << 24) < 0 ? "signed" : "unsigned");
// C++, unsigned 8-bit byte promotes to signed.
printf(LANG ", unsigned char variable promotes to %s.\n",
(a << 24) < 0 ? "signed" : "unsigned");
// C++, unsigned char variable promotes to signed.
printf(LANG ", unsigned char bitfield promotes to %s.\n",
(charfield.a << 24) < 0 ? "signed" : "unsigned");
// C++, unsigned char bitfield promotes to signed.
return 0;
}
The comments show the results on Visual Studio 2005 C++. In most
cases, the result is signed.
I think the confusion is what defines the length of the rvalue? Is it
of unsigned int type, in which case it would promote to unsigned int
for a typical implementation, or is it an eight bit value, in which
case it would promote to signed int.
The C++ standard seems fairly unambigous that the rvalue should be
signed. The following thread on the gcc support list supports this
conclusion:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16376
Still, you gotta wonder why so many implementations appear to implement
this incorrectly.
rCs
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: rcs@sei.cmu.edu (Robert Seacord)
Date: Thu, 11 Jan 2007 22:25:04 GMT Raw View
ISO/IEC 14882-2003 Section 4.5, "Integral promotions" [conv.prom]
[ISO/IEC 14882-2003] says:
An rvalue for an integral bit-field (9.6) can be converted to an rvalue
of type int if int can represent all the values of the bit-field;
otherwise, it can be converted to unsigned int if unsigned int can
represent all the values of the bit-field.
In the following example:
struct {
unsigned int a: 8;
} bits = {255};
int main() {
cout << "unsigned 8-bit field promotes to"
<< (bits.a << 24) < 0 ? "signed" : "unsigned"
<< endl;
}
The type of the expression (bits.a << 24) should be int for a (typical)
architecture where int is represented by a 32-bit (or even a 16-bit)
value. However, most implementations including Microsoft Visual Studio
7.1 and g++ version 4.1.0 promote (bits.a << 24) to unsigned int.
Do I misunderstand, or is this some sort of weird conspiracy? 8^)
rCs
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]