Bit field types and promotions

Bit field types and promotions

Post by algran » Sat, 24 Dec 2005 23:55:10


Is it true that with 32-bit int, and 64-bit long long,
and given the type

struct { unsigned long long x:40; } x;

no promotion occurs in the expression

x.a + x.a

its result is a 40-bit type, i.e. the result of the
addition truncates to 40 bits. This belief appears to
derive from detailed reading of 6.3.1.1, 6.3.1.8 and
6.7.2.1#9.

I find this all hard to accept, it seems counter-
intuitive, non-C-like (if first-class bit-sized types
are something we want, why not have them
smaller than int too?), and almost certainly not
true in C++.

Yet gcc seems to be heading that way. See for
example the regression test at

http://www.yqcomputer.com/
 
 
 

Bit field types and promotions

Post by Thad Smit » Sun, 25 Dec 2005 10:15:00


An implementation is free is do that as an extension, but Standard C
does not support bit-fields of type unsigned long long.

--
Thad

 
 
 

Bit field types and promotions

Post by jacob navi » Sun, 25 Dec 2005 10:27:09


XXXX@XXXXX.COM a rit :

Mmm could you please elaborate?

"counter-intuitive" is surely not. What is so surprising?
You add 40 bits number to obtain a 40 bits result. Seems
100% normal and "C-like" to me.

Anyway what is the result of:
struct { unsigned a:10; } x,result;
result.a = x.a+x.a; // --> ???

It is an addition truncated to 10 bits, I am sorry...
 
 
 

Bit field types and promotions

Post by kuype » Mon, 26 Dec 2005 03:10:49


6.7.2.1p4: "A bit-field shall have a type that is a qualified or
unqualified version of _Bool, signed int, unsigned int, or some other
implementation-defined type."


The width in a bit field declaration only controls how the value of
that member is stored. Once that value is retrieved, it has no effect
on the type of the expression which accesses that member. If the
declared type of 'a' were one that is legal for a bit-field, then the
type and value of the expression x.a+x.a would be determined by exactly
the same rules that would apply if the ":40" were removed from the
declaration of 'a'.
 
 
 

Bit field types and promotions

Post by Me » Thu, 29 Dec 2005 13:22:24


It's true that no promotion occurs but it's false that the result is a
40-bit type. I think a better example for you is:

struct {
unsigned long long a : 2;
} x;

+x.a

Q: Is an implementation allowed to have the type of that expression be
int?
A: No, it must be unsigned long long (ignoring compiler extensions).

Bit-fields are just an attribute used for controlling bit-packing and
padding so you can just think of them as regular integer types with
some restrictions (sizeof and the address operator mainly). To convince
yourself of this, read the definition of integer type (6.2.5) and see
that it doesn't include bit-fields as separate types, so all the parts
in 6.3 that deal with integer rank/conversions/promotions don't care
about the bit-field width, just the type (though there is one stupidity
of C to remember: the compiler is allowed to treat plain integers as
unsigned in bit-fields, but that just acts as if you specified it with
unsigned).
 
 
 

Bit field types and promotions

Post by David R Tr » Fri, 30 Dec 2005 02:19:27


As other posters have pointed out, unsigned long long bitfields are
an implementation-defined extension.

However, based on the way ISO C handles integer promotions, it
seems that what _should_ happen is that the result of the
addition is a full unsigned long long (64-bit) untruncated result.

Obviously, assigning that result to a 40-bit bitfield will then
result in truncation, but the intermediate result of the addition
should (probably) not be truncated. I add the "probably"
caveat because the whole thing falls under "implemenation-defined
behavior", and you could argue that GCC is conforming in
that regard, even if it is unintuitive.

-drt
 
 
 

Bit field types and promotions

Post by DAGwy » Fri, 30 Dec 2005 02:24:17


A bit-field member has a storage type only; in expressions
it is promoted to a "normal" integer type, which combines
according to the usual rules. If the result of an expression
is stored into a bit-field member and is not representable,
then of course u.b. occurs.
 
 
 

Bit field types and promotions

Post by Keith Thom » Fri, 30 Dec 2005 02:44:01

"DAGwyn" < XXXX@XXXXX.COM > writes:


Is it undefined behavior, or is it merely the implementation-defined
result or implementation-defined signal that results from a conversion
(or well-defined range reduction if the bit-field is unsigned)?

--
Keith Thompson (The_Other_Keith) XXXX@XXXXX.COM < http://www.yqcomputer.com/ ~kst>
San Diego Supercomputer Center <*> < http://www.yqcomputer.com/ ~kst>
We must do something. This is something. Therefore, we must do this.
 
 
 

Bit field types and promotions

Post by Tim Rentsc » Fri, 30 Dec 2005 17:00:24

XXXX@XXXXX.COM writes:


[ struct { unsigned long long a:40; } x; /* correction */ ]



What matters is 6.7.2.1 p9: "A bit-field is interpreted as a signed
or unsigned integer type consisting of the specified number of bits."



Considering the set of people who posted this comment or something
similar, it's probably some sort of C folklore. But it's not what
the Standard says.

The type of 'x.a' is a 40-bit (unsigned) integer type (6.7.2.1 p9).

The expression 'x.a + x.a' first goes through the integer promotions
for each of the two operands. Assuming that an 'int' is only 32 bits,
the integer promotions leave the 40-bit types unchanged (6.3.1.1 p2).

The plus operator then applies the usual arithmetic conversions. The
two (promoted) operands both have the same 40-bit (unsigned) integer
type, so the usual arithmetic conversions leave the types unchanged
(6.3.1.8 p1).

The result of the plus operator has type that is the type of the
operands after the conversions. "Unless explicitly stated otherwise,
the common real type is also the corresponding real type of the
result, ..." (6.3.1.8 p1).

Hence the type of 'x.a + x.a' is a 40-bit unsigned integer type. If
unsigned long long has 64 bits, then the result may be different than
what would be obtained if the result type were unsigned long long.

Some examples (assuming 32-bit ints, 64 bit long longs):

1. Will "less" or "not less" be printed?

struct { unsigned long long a:40; } x = {0};

if( x.a - 1LL < 0 ) printf( "less\n" );
else printf( "not less\n" );


2. Will "less" or "not less" be printed?

struct { unsigned long long a:2; } x = {0};

if( x.a - 1 < 0 ) printf( "less\n" );
else printf( "not less\n" );


3. Will "less" or "not less" be printed?

struct { unsigned long long a:40; } x = {0};

if( (x.a + x.a) - 1LL < 0 ) printf( "less\n" );
else printf( "not less\n" );


4. Will "less" or "not less" be printed?

struct { unsigned long long a:40; } x = { 0x8000000000uLL };

if( (x.a + x.a) < x.a ) printf( "less\n" );
else printf( "not less\n" );


The answer in every case is "less". If the (promoted or converted)
type of x.a in the expressions were type 'unsigned long long', the
answers would be "not less". Note that example 2 can be tried with
'unsigned' in place of 'unsigned long long', in case someone doesn't
have access to a compiler that supports extended bitfield types.
 
 
 

Bit field types and promotions

Post by Tim Rentsc » Fri, 30 Dec 2005 17:13:38

"Me" < XXXX@XXXXX.COM > writes:



The rules for precision, integer conversion rank, and integer promotions
together require that the result type be 'int'.



Did you even bother to read 6.7.2.1 p9?
 
 
 

Bit field types and promotions

Post by Tim Rentsc » Fri, 30 Dec 2005 17:24:29

"David R Tribble" < XXXX@XXXXX.COM > writes:



Do you accept that the type of x.a is a 40-bit (unsigned) integer
type? Have you read 6.7.2.1 p9?

Assuming you accept that the type of x.a is a 40-bit integer
type, how do you get that the type of 'x.a + x.a' is anything
other than that same 40-bit type?
 
 
 

Bit field types and promotions

Post by Tim Rentsc » Fri, 30 Dec 2005 17:29:16

"DAGwyn" < XXXX@XXXXX.COM > writes:



Chapter and verse, please.
 
 
 

Bit field types and promotions

Post by David R Tr » Sat, 31 Dec 2005 01:26:26

David R Tribble writes:



Yeah, just now:
A bit-field is interpreted as a signed or unsigned integer type
consisting of the specified number of bits.

But that does not affect what I _think_ should happen.



True, a literal reading of the standard certainly implies that bitfield
values larger than unsigned int will be treated as n-bit types,
where n is more than the bits in an unsigned long.

This could be read as a back-door way to force the compiler
to implement n-bit integer types, for arbitrary n between the
sizes of int and long long int.


But "the spirit of C" is what makes me think that the bitfield
operands within the expression _should_ be converted into
full-sized standard integer types, i.e, unsigned long long.

It should be clear that my "should" in the sentence above is
my opinion about what _should_ happen and not what _does_
happen.

-drt
 
 
 

Bit field types and promotions

Post by Tim Rentsc » Sat, 31 Dec 2005 03:16:24

"David R Tribble" < XXXX@XXXXX.COM > writes:



Ahh, ok.



I presume you meant where n is more than the bits in an unsigned int.



The reading I'm suggesting doesn't force a compiler to implement such
types, since bitfields of type larger than signed/unsigned int are
an extension, not a requirement.



For non-bitfield types: types shorter than signed/unsigned int are
promoted to one of the int types, and types longer than an int type
operate in the smallest type that's at least as large as each of the
operands.

Given that, can you explain what's wrong with having the same rule for
bitfields as for non-bitfields?



Yes, I appreciate the clarification.
 
 
 

Bit field types and promotions

Post by Me » Sat, 31 Dec 2005 08:47:22

im Rentsch wrote:

The standard doesn't say what "interpreted" means in this context. I
think it means for the initial read or the final write, it treats it as
a integer type with whatever bits, you think it creates a new integer
type. Both are valid interpretations (puns are fun), but IMHO the
standard doesn't really have wording to take account for it in most of
6.3.


I'm kind of agreeing with you, but I'm kind of not. The simplest place
to start is:

6.3.1.1/2 "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"

My guess is that the comittee intended:

struct {
unsigned a : 2;
} i;

+i.a;

to promote to int as opposed to unsigned int. I would argue this is
wrong because I take "type" to mean "integer type" (and because I'm a
fan of unsigned preserving conversions), but I can see why they would
want it to act like that. So if I would have to guess, this is one of
the places the "interpreted" part of 6.7.2.1/9 takes place. But this
leads to two tricky examples to compare against the current wording:

(assume 32-bit int, 64-bit long, and 64-bit long long)

////////////////////////
struct {
unsigned long a : 51;
unsigned long b : 50;
} x;

x.a + x.b; // #A#

/////////////////////////
struct {
unsigned long a : 50;
unsigned long long b : 40;
} y;

y.a + y.b; // #B#

6.3.1.8/1:

- If both operands have the same type, then no further conversion is
needed.

(my interpretation)
#A# - Both operands stay as unsigned long and no further conversion is
needed

(your interpretation)
#A# - unsigned long : 51 is different than unsigned long : 50, so
further conversion is needed.

- Otherwise, if both operands have signed integer types or both have
unsigned integer types, the operand with the type of lesser integer
conversion rank is converted to the type of the operand with greater
rank.

(your interpretation)
#A# - Ok, now we need 6.3.1.1/1, which talks about conversion ranks
which involve the integer types (6.2.5). Neither sections take
bit-fields into account, so now what?

#B# - Ditto, but this one is more trickier because unsigned long : 50
is larger in width than unsigned long long : 40 but the rank of long is
smaller than long long.