448,843 Members | 1,551 Online
Need help? Post your question and get tips & solutions from a community of 448,843 IT Pros & Developers. It's quick & easy.

# Bit-fields vs integral promotions

 P: n/a Suppose I'm using an implementation where an int is 16 bits. In the program below, what function is called in the first case, and what is called in the second case? Also, if there is a difference between C89 and C99, I would like to know. I have tried with different compilers, and I see some differences. Before I file a bug report with my C vendor, I would like to know what the correct behavior is. struct S { unsigned a:4; unsigned b:16; }; foo(); bar(); main() { struct S s; s.a = s.b = 0; if (s.a - 5 < 0) foo(); else bar(); if (s.b - 5 < 0) foo(); else bar(); } Aug 23 '07 #1
14 Replies

 P: n/a On Thu, 23 Aug 2007 18:08:29 +0200 (CEST), Thurston Manson

 P: n/a Jack Klein wrote: > As for an unsigned bit-field holding 16 bits on a platform where int has 16 bits, this is quite clear. It must promote to unsigned int, therefore "s.b - 5" becomes (unsigned int)(UINT_MAX - 4), otherwise known as 65531. It's not that clear. If signed int can hold all the values of unsigned int (IIRC, there are platforms without "native" unsigned arithmetic for which this is the case), then, it should be promoted to int. -- You can contact me at Aug 24 '07 #3

 P: n/a On Fri, 24 Aug 2007 11:03:54 +0200, "André Gillibert"

 P: n/a Jack Klein wrote: Please note that I specifically said "on a platform where int has 16 bits". A platform such as you allude to must have at least 17 bits in a signed int. Yep. 18 bits machine did exist... I doubt that there has ever been any 18 bits machine with 1 padding bit, and one sign bit, without unsigned arithmetic. Anyway, the standard *permits* that, even if it's practically impossible to find any existing platforms that uses such a model. -- You can contact me at Aug 24 '07 #5

 P: n/a Thurston Manson wrote: > Suppose I'm using an implementation where an int is 16 bits. In the program below, what function is called in the first case, and what is called in the second case? Also, if there is a difference between C89 and C99, I would like to know. I have tried with different compilers, and I see some differences. Before I file a bug report with my C vendor, I would like to know what the correct behavior is. struct S { unsigned a:4; unsigned b:16; }; foo(); bar(); main() { struct S s; s.a = s.b = 0; if (s.a - 5 < 0) foo(); else bar(); if (s.b - 5 < 0) foo(); else bar(); } This won't even compile. foo and bar are never defined. main should return an int (required in C99). The return is missing (required in C90). You are comparing signed and unsigned values. No compiler bugs have been evidenced. -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. -- Posted via a free Usenet account from http://www.teranews.com Aug 25 '07 #6

 P: n/a Jack Klein wrote: > .... snip ... > Please note that I specifically said "on a platform where int has 16 bits". A platform such as you allude to must have at least 17 bits in a signed int. I don't believe you can have such without having a 17 bit unsigned int, thus leading to a 18 bit int, and thence to an 18 bit unsigned, and .... I don't think use of trap bits can affect this. Unsigned to signed conversion is always possible because of the modulo unsigned arithmetic. -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. -- Posted via a free Usenet account from http://www.teranews.com Aug 25 '07 #7

 P: n/a CBFalconer wrote: Jack Klein wrote: ... snip ... >Please note that I specifically said "on a platform where int has16 bits". A platform such as you allude to must have at least 17bits in a signed int. I don't believe you can have such without having a 17 bit unsigned int, thus leading to a 18 bit int, and thence to an 18 bit unsigned, and .... I don't think use of trap bits can affect this. Unsigned to signed conversion is always possible You may be correct (I do not have time to research the Standard to come up with a conclusion) but not for the reason you give. because of the modulo unsigned arithmetic. Modulo unsigned arithmetic only guarantees that signed to unsigned is always possible it has nothing to say about what happens when a sufficiently large unsigned value is converted to a signed one. -- Note that robinton.demon.co.uk addresses are no longer valid. Aug 25 '07 #8

 P: n/a CBFalconer said: Thurston Manson wrote: >> >>struct S { unsigned a:4; unsigned b:16;};foo();bar();main() { struct S s; s.a = s.b = 0; if (s.a - 5 < 0) foo(); else bar(); if (s.b - 5 < 0) foo(); else bar();} This won't even compile. Yes, it will. foo and bar are never defined. So? They are implicitly declared by first use. That's enough for compilation. main should return an int (required in C99). Clearly this is C90 code. The return is missing (required in C90). Not so. The return status is undefined, but the behaviour of the program is not. In fact, I think that the TU is strictly conforming. I'm not saying I approve of omitting the return statement, of course - I don't. You are comparing signed and unsigned values. So? No compiler bugs have been evidenced. Indeed. -- Richard Heathfield Email: -www. +rjh@ Google users: "Usenet is a strange place" - dmr 29 July 1999 Aug 25 '07 #9

 P: n/a Francis Glassborow wrote: CBFalconer wrote: .... snip ... >>I don't think use of trap bits can affect this. Unsigned to signedconversion is always possible because of the modulo unsignedarithmetic. You may be correct (I do not have time to research the Standard to come up with a conclusion) but not for the reason you give. Modulo unsigned arithmetic only guarantees that signed to unsigned is always possible it has nothing to say about what happens when a sufficiently large unsigned value is converted to a signed one. No, the standard says that any attempt to store a value outside its capacity in a signed int is undefined behaviour. -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. -- Posted via a free Usenet account from http://www.teranews.com Aug 25 '07 #10

 P: n/a CBFalconer wrote: Francis Glassborow wrote: >CBFalconer wrote: ... snip ... >>>I don't think use of trap bits can affect this. Unsigned to signedconversion is always possible because of the modulo unsignedarithmetic. You may be correct (I do not have time to research the Standard tocome up with a conclusion) but not for the reason you give.Modulo unsigned arithmetic only guarantees that signed to unsignedis always possible it has nothing to say about what happens when asufficiently large unsigned value is converted to a signed one. No, the standard says that any attempt to store a value outside its capacity in a signed int is undefined behaviour. C&v, please. Aug 25 '07 #11

 P: n/a CBFalconer writes: >Jack Klein wrote: >Please note that I specifically said "on a platform where int has16 bits". A platform such as you allude to must have at least 17bits in a signed int. I don't believe you can have such without having a 17 bit unsigned int, thus leading to a 18 bit int, and thence to an 18 bit unsigned, and .... Yes you can. C99 6.2.5p9 (Types): "The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the representation of the same value in each type is the same." Also 6.2.6.2p2 (Integer types): "if there are M value bits in the signed type and N in the unsigned type, then M <= N". [And p1 says the sign bit is not counted as a value bit in signed types.] I don't think use of trap bits can affect this. C99 defines trap representations, not trap bits. Padding bits can cause a value to be a trap representation (Note 44 in 6.2.6.2 uses a parity bit as an example), but I think value and sign bits can too for signed types: Negative zero, or -_MAX-1 when _MIN == -_MAX. -- Hallvard Aug 25 '07 #12

 P: n/a CBFalconer CBFalconer wrote: ... snip ... >>>I don't think use of trap bits can affect this. Unsigned to signedconversion is always possible because of the modulo unsignedarithmetic. You may be correct (I do not have time to research the Standard tocome up with a conclusion) but not for the reason you give.Modulo unsigned arithmetic only guarantees that signed to unsignedis always possible it has nothing to say about what happens when asufficiently large unsigned value is converted to a signed one. No, the standard says that any attempt to store a value outside its capacity in a signed int is undefined behaviour. Not quite. Conversion to a signed type, if the value can't be represented, yields an implementation-defined result or raises an implementation-defined signal. (Overflowing arithmetic operations on signed types, on the other hand, invoke undefined behavior.) -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <* "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" Aug 25 '07 #13

 P: n/a Hallvard B Furuseth wrote: CBFalconer writes: >Jack Klein wrote: >>Please note that I specifically said "on a platform where int has16 bits". A platform such as you allude to must have at least 17bits in a signed int. I don't believe you can have such without having a 17 bit unsignedint, thus leading to a 18 bit int, and thence to an 18 bitunsigned, and .... Yes you can. C99 6.2.5p9 (Types): "The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type, and the representation of the same value in each type is the same." Also 6.2.6.2p2 (Integer types): "if there are M value bits in the signed type and N in the unsigned type, then M <= N". [And p1 says the sign bit is not counted as a value bit in signed types.] >I don't think use of trap bits can affect this. C99 defines trap representations, not trap bits. Padding bits can cause a value to be a trap representation (Note 44 in 6.2.6.2 uses a parity bit as an example), but I think value and sign bits can too for signed types: Negative zero, or -_MAX-1 when _MIN == -_MAX. Maybe I should just add a note to all my software: No protection against M==N in 6.2.6.2p2 is afforded. :-) -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. -- Posted via a free Usenet account from http://www.teranews.com Aug 26 '07 #14

 P: n/a Jack Klein 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. [...] > So in C99, even though "A bit-field of type _Bool, int, signed int, or unsigned int" participates in the integer promotions, it is converted to signed in if "an int can represent all values of the original type", but there has been quite some discussion about whether "the original type" means either: 1. The "original type" of an unsigned int bit-field is unsigned int, regardless of the fact that the number of bits used is less than the value bits in a signed int, so an unsigned int bit-field always promotes to unsigned int. Even though all the values that can actually fit into a small unsigned int bit-field are within the range of values that an int can hold. 2. The "original type" is the user-defined "unsigned integer type consisting of the specified number of bits." [...] > For C90, things are even muddier. [...] The committee has been clarified their intent through a C90 DR122: http://www.open-std.org/jtc1/sc22/wg...cs/dr_122.html > Every compiler I have ever tested this on always promotes unsigned bit-fields to unsigned int, regardless of the number of bits. This includes at least Microsoft VC++ 6.0 an 2005 Express, Borland C++ Builder X, Peles C, and MinGW. So if an implementation claiming its conformance to the standard ignores the number of bits used for a bit-field of unsigned int type in performing the integral promotions, it is not conforming. -- Jun, Woong (woong at icu.ac.kr) Samsung Electronics Co., Ltd. ``All opinions expressed are mine, and do not represent the official opinions of any organization.'' Aug 29 '07 #15

### This discussion thread is closed

Replies have been disabled for this discussion.