Bit-fields and integral promotion

L

Lawrence Kirby

In message <[email protected]>
....


17-bit bitfields are not permitted on 16-bit systems, so the only issue is
that 16-bit ones promote differently to smaller ones. Just like unsigned
short promoting differently to unsigned char.

The standard says in 6.7.21p4

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

So if an implementation supports, say, long and unsigned long bit-fields
as implementation-defined types what constraints on the implementation of
those does the standard specify?

Lawrence
 
K

Keith Thompson

CBFalconer said:
Also in stddef.h and several other places.

No, <stddef.h> doesn't define EOF. (NULL is defined in several
headers; is that what you were thinking of?)

It's interesting to note that the standard's section on <ctype.h>
refers to the EOF macro, but the macro isn't defined in <ctype.h>.
All it says, though, is that the functions have to accept arguments
with the same value as EOF. An implementer of <ctype.h> has to know
the value of EOF (or has to implement the functions so they accept any
negative argument), but the interface doesn't need it.
 
C

CBFalconer

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. There have been
several instances posted in this thread (at least on c.l.c) where
that action leaves the poor programmer in a quandary as to what the
code will do on another machine. One example is the 16 bit
unsigned field, which will be interpreted differently on a 32 bit
and on a 16 bit int machine.

I came to this conclusion from first principles by considering the
rational code generation actions, all elaborated elsewhere in this
thread. This also provides the known treatment from the point of
the language user.
 
A

Alex Fraser

CBFalconer said:
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.

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.
There have been several instances posted in this thread (at least on
c.l.c) where that action leaves the poor programmer in a quandary as to
what the code will do on another machine. One example is the 16 bit
unsigned field, which will be interpreted differently on a 32 bit
and on a 16 bit int machine.

Just like a 16-bit unsigned short.
I came to this conclusion from first principles by considering the
rational code generation actions, all elaborated elsewhere in this
thread.

The only difference between what you suggest and what most people seem to
think the standard says is that for some unsigned bit-fields (those with max
value <= INT_MAX), the latter says promote to signed int whereas you say
promote to unsigned int.

However, code generated for promotion of an unsigned bit-field to signed int
is identical to that for promotion of an unsigned bit-field to unsigned int,
provided the representations of all positive signed int values are identical
to the same unsigned int value. This is normally, if not always, the case.

Therefore I fail to see how considering code generation, rational or
otherwise, could lead you to a conclusion either way on this issue.

Alex
 
C

CBFalconer

Keith said:
CBFalconer said:
Keith said:
[...]
I know EOF should be negative. But I cannot find the words that
require it to be different from any unsigned char for a
_freestanding_ implemantation (which may misses the <ctype.h>
header.)

EOF is defined in <stdio.h>, which freestanding implementations
aren't required to provide.

Also in stddef.h and several other places.

No, <stddef.h> doesn't define EOF. (NULL is defined in several
headers; is that what you were thinking of?)

I goofed again. Maybe it's just as well Dan Pop is missing.
 
C

CBFalconer

Alex said:
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.

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?
Just like a 16-bit unsigned short.


The only difference between what you suggest and what most people
seem to think the standard says is that for some unsigned
bit-fields (those with max value <= INT_MAX), the latter says
promote to signed int whereas you say promote to unsigned int.

However, code generated for promotion of an unsigned bit-field
to signed int is identical to that for promotion of an unsigned
bit-field to unsigned int, provided the representations of all
positive signed int values are identical to the same unsigned
int value. This is normally, if not always, the case.

No, it is not. It is dependant on the value of the sign bit of the
restricted bit field, if you insist on the so called 'value
preserving' interpretation here rather than 'signed preserving'.
Therefore I fail to see how considering code generation, rational
or otherwise, could lead you to a conclusion either way on this
issue.

Simple - signed preservation leads to consistent interpretation by
the user, minimization of generated code, and reduction of code in
the code generator. Due to the ambiguity of the present standard
the opportunity exists to specify this correctly. Do so.
 
M

Mark Piffer

Kevin said:
In message <[email protected]>
architecture).

No more absurd than

unsigned char uc;
unsigned short us;

uc + 1 -> int
us + 1 -> unsigned int

is it? Unsigned short promotes to unsigned int only because it is 16 bits
like int. Unsigned char does not. On another, 32-bit, implementation unsigned
short would promote to int. This "absurdity" already exists for the main
types.
True, but what I was pointing out is that you have another
implementation dependent partial order of conversion ranks that you
need to fit (mentally) into the existing one, when with the sign
preservation rule you could have got away very cheap.
17-bit bitfields are not permitted on 16-bit systems, so the only issue is
that 16-bit ones promote differently to smaller ones. Just like unsigned
short promoting differently to unsigned char.
To me 6.7.2.1p4 reads as if the width is an implementation defined
thing, just the use of a bitfield exceeding the width of an int in a
conversion or promotion is left unspecified (I found nothing conclusive
in 6.3). It seems reasonable that at least an assignment is allowed.
OTOH, this makes my previous answer pointless, as any use of an
unsigned bitfield in most expressions is either unproblematic (positive
int -> unsigned int) or not defined at all. (shrug)

Mark
 
T

Tony Finch

CBFalconer said:
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?

Use an unsigned bit field of course.
Simple - signed preservation leads to consistent interpretation by
the user, minimization of generated code, and reduction of code in
the code generator. Due to the ambiguity of the present standard
the opportunity exists to specify this correctly. Do so.

That would be to reverse a decision made over 15 years ago. If you
want K&R C you know where to find it...

Tony.
 
L

Lawrence Kirby

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.

Unfortunately there is just too much else in the standard that depends on
bit-field width being considered as a part of the type. Consider for
example assigning an out of range value to an unsigned bit-field in the
context of 6.3.1.3p2.
There have been
several instances posted in this thread (at least on c.l.c) where
that action leaves the poor programmer in a quandary as to what the
code will do on another machine. One example is the 16 bit
unsigned field, which will be interpreted differently on a 32 bit
and on a 16 bit int machine.

That's an example of the problem with the overall value-preserving
rules, not just bit-fields. You have no argument from me that
unsigned-preserving rules would have been much better for the language.
But that's not what we have and trying to make bit-fields unsigned
preserving while char and short promotions remain value preserving is
probably not a good idea.
I came to this conclusion from first principles by considering the
rational code generation actions, all elaborated elsewhere in this
thread. This also provides the known treatment from the point of
the language user.

Whether you use value or unsigned preserving rules doesn't make any
difference to code generation for the promotion. In both cases the result
of promoting an unsigned value is a positive value which has the same
representation in a signed or unsigned int type.

Lawrence
 
A

Alex Fraser

[snip]
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.

No! An unsigned 1 bit bit-field can (obviously) hold the values 0 and 1.
"Value preserving" promotion should result in a signed int with the same
value (otherwise "value preserving" would be a pretty stupid name).

In code generation terms, you only copy/move the sign bit when the
unpromoted type is signed, not when the promoted type is signed. Perhaps
this example exposes the root of your misunderstanding.

Alex
 
L

Lawrence Kirby

[snip]
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.

No! An unsigned 1 bit bit-field can (obviously) hold the values 0 and 1.
"Value preserving" promotion should result in a signed int with the same
value (otherwise "value preserving" would be a pretty stupid name).

To be honest it is. Any promotion mechanism that didn't preserve value
would be rather silly. Unsigned preserving promotion also preserves value.
So preserving value is not a distinguishing feature of the standard's
integer promotions.

Lawrence
 
K

Kevin Bracey

In message <[email protected]>
Lawrence Kirby said:
The standard says in 6.7.21p4

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

So if an implementation supports, say, long and unsigned long bit-fields
as implementation-defined types what constraints on the implementation of
those does the standard specify?

Such things are not subject to integer promotions, according to 6.3.1.1p2.
It doesn't seem terribly concrete, but I think that may mean that a "long:4"
just functions as a long? What about a "unsigned char:4"? Does it act as a
unsigned char, and hence get promoted?

Ew. Bitfields on larger types are not something I'm familiar with, as our
systems don't support it.
 
J

James Kuyper

CBFalconer said:
....
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

This "attitude" (correct interpretation of the standard, as confirmed by
the Committee's decision on DR 122), calls for value-preserving
conversion of the 1 bit field to int. Therefore, if it's declared as
unsigned, the result must be either 0 or 1, not -1.
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?

"If the value 0 or 1 is stored into a nonzerowidth bit-field of type
_Bool, the value of the bit-field shall compare equal to the value stored."

The value-preserving conversion to int can therefore only produce a 0 or
a 1.
 
C

CBFalconer

Tony said:
.... snip ...


That would be to reverse a decision made over 15 years ago. If you
want K&R C you know where to find it...

No such decision has been embodied in the standard, so it doesn't
count.
 
C

CBFalconer

Lawrence said:
Unfortunately there is just too much else in the standard that
depends on bit-field width being considered as a part of the type.
Consider for example assigning an out of range value to an unsigned
bit-field in the context of 6.3.1.3p2.

For this purpose that is just one more black cat in the dark. The
values are known to be positive, and the standard insists on binary
representation, so masking off a set of less significant bits
produces the same answer for all three flavors. All that has to be
done is make a conversion to some form of unsigned (if needed) in
the original, not in the potential 30 odd or more types pseudo
created by bit fields.
 
J

James Kuyper

CBFalconer said:
Tony Finch wrote: ....


No such decision has been embodied in the standard, so it doesn't
count.

The decision merely confirmed a meaning that was already (albeit
unclearly) embodied in the standard.
 
T

Tony Finch

CBFalconer said:
No such decision has been embodied in the standard, so it doesn't
count.

Er, what? K&R C was signedness-preserving but ANSI C has deliberately
different promotion rules.

Tony.
 
A

Alex Fraser

Lawrence Kirby said:
To be honest it is. Any promotion mechanism that didn't preserve value
would be rather silly. Unsigned preserving promotion also preserves
value. So preserving value is not a distinguishing feature of the
standard's integer promotions.

Granted; "unsigned preserving" is logically a subclass of "value preserving"
but I think it's basically a case of giving a concise name to the behaviour.
There's no immediately obvious and superior alternative that I can think of.

Alex
 

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,997
Messages
2,570,240
Members
46,829
Latest member
KimberAlli

Latest Threads

Top