Question about bitfield promotion/cast to integer

R

Ray

When a single-bit bitfield that was formed from an enum
is promoted/cast into an integer, does ANSI C say anything
about whether that integer should be signed or unsigned?
SGI IRIX cc thinks it is an unsigned integer, so I
see a +1 if the bit is set. Microsoft VC++ thinks it's
signed, so I see -1 if the bit is set.

Ex.

typedef enum {
ZERO = 0,
ONE = 1
} test_enum_t;

typedef struct {
test_enum_t bitfield : 1;
} enum_struct_t;



int main( void )
{
enum_struct_t enum_struct;

enum_struct.bitfield = 1; /* bit is set */

if ( (test_num_t) enum_struct.bitfield == ONE ) {
printf( "Bit is ONE\n" ); /* cast as unsigned int? */
}
else {
printf( "Bit is ZERO\n" ); /* cast as signed int? */
}

return 0;
}


Thanks!
 
B

Ben Pfaff

When a single-bit bitfield that was formed from an enum
is promoted/cast into an integer, does ANSI C say anything
about whether that integer should be signed or unsigned?

Bit-fields may only portably have _Bool, signed int, or unsigned
int type.
 
A

Al Bowers

Ray said:
When a single-bit bitfield that was formed from an enum
is promoted/cast into an integer, does ANSI C say anything
about whether that integer should be signed or unsigned?
SGI IRIX cc thinks it is an unsigned integer, so I
see a +1 if the bit is set. Microsoft VC++ thinks it's
signed, so I see -1 if the bit is set.

From the standard.
6.7.2.1 Structure and union specifiers
....
9 A bit-field is interpreted as a signed or unsigned integer
type consisting of the specified number of bits. See(104).
If the value 0 or 1 is stored into a nonzero-width bit-field
of type _Bool, the value of the bit-field shall compare
equal to the value stored.

104) As specified in 6.7.2 above, if the actual type specifier
used is int or a typedef-name defined as int, then it is
implementation-defined whether the bit-field is signed or unsigned.
 
J

Jack Klein

Bit-fields may only portably have _Bool, signed int, or unsigned
int type.

Which fails to answer the question the OP asked, so why did you
bother? And bit-fields may indeed be int portably, so long as the
sign bit/msb is always 0. A 4-bit bit-field defined as just "int" may
portably hold the values 0 through 7 an any and every implementation.

As for the enum, it is perfectly legal if the implementation documents
that it accepts it. It is also perfectly portable to any
implementation that provides an option to treat all enumerated types
as ints, and most do.

C99 6.7.2.1 para 4:

"4 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."
 
J

Jack Klein

When a single-bit bitfield that was formed from an enum
is promoted/cast into an integer, does ANSI C say anything

If it is cast, it becomes whatever it is cast to. That has nothing to
do with implicit conversions.
about whether that integer should be signed or unsigned?
SGI IRIX cc thinks it is an unsigned integer, so I
see a +1 if the bit is set. Microsoft VC++ thinks it's
signed, so I see -1 if the bit is set.


A single bit bit-field must promote to a signed int. In fact, any
bit-field with no more than 15 bits must promote to signed int, even
if it is defined as an unsigned int bit-field.

========
6.3.1.1 Para 2 & 3:

2. The following may be used in an expression wherever an int or
unsigned int may be used:

— An object or expression with an integer type whose integer
conversion rank is less than the rank of int and unsigned int.

— A bit-field of type _Bool, int, signed int, or unsigned int.

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.
These are called the integer promotions. All other types are
unchanged by the integer promotions.

3. The integer promotions preserve value including sign. As discussed
earlier, whether a ‘‘plain’’ char is treated as signed is
implementation-defined.

========

Since the only possible values of a 1 bit unsigned int bit-field are 0
and -1, so a signed int can represent all possible values. The only
possible values of a 1 bit unsigned int bit-field are 0 and +1, and a
signed int can represent all possible values. So a single bit
bit-field defined as int must promote to a signed int in an
expression, regardless of whether the implementation considers the
bit-field to be signed or unsigned int.
Ex.

typedef enum {
ZERO = 0,
ONE = 1
} test_enum_t;

typedef struct {
test_enum_t bitfield : 1;
} enum_struct_t;



int main( void )
{
enum_struct_t enum_struct;

enum_struct.bitfield = 1; /* bit is set */

if ( (test_num_t) enum_struct.bitfield == ONE ) {
^^^^^^^^^^^^
This is a cast, and it is meaningless. The value of the bit-field
will be converted to a test_num_t, which either is an int or will be
automatically promoted to an int by the rules I quoted above.
printf( "Bit is ONE\n" ); /* cast as unsigned int? */

There is no cast here. There is no such thing as an implicit cast in
C. A cast is an explicit conversion, which might or might not be an
acceptable automatic conversion without a cast.


}
else {
printf( "Bit is ZERO\n" ); /* cast as signed int? */
}

return 0;
}

You are confused, you are comparing the constants ONE and ZERO against
the value of your bit-field converted to a (signed) int.

What is confusing you is the fact that when a bit-field is defined as
"int", or a type such as an enumerated type, without specifying signed
int or unsigned int, it is up to the implementation to decide whether
to treat it as signed or unsigned. Exactly the same as whether
"plain" char is signed or unsigned.

Your compiler treats your unspecified bit-fields as unsigned, which
should be documented in its documentation. That unsigned bit-field
promotes to the signed int value of 1 in an expression.

If your compiler treated that bit-field as unsigned, your second
printf() statement would execute, but it would lie, because your
bit-field would convert to the int value -1.

Try:

printf("Bit is %d\n", enum_struct.bitfield);

Then try changing the type of the bit-field to, in turn, int, signed
int, unsigned int, and see what is output.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top