Help with bit-field semantics in C and C++
Gabriel Dos Reis
gdr@integrable-solutions.net
Tue Aug 24 20:47:00 GMT 2004
Mike Stump <mrs@apple.com> writes:
| On Tuesday, August 24, 2004, at 12:32 PM, Gabriel Dos Reis wrote:
|
| > Mike Stump <mrs@apple.com> writes:
| >
| > | On Tuesday, August 24, 2004, at 10:51 AM, Joe Buck wrote:
| > | > On Tue, Aug 24, 2004 at 11:05:41AM -0600, Roger Sayle wrote:
| > | >> The problem here is that a C++ enum can hold values outside the
| > range
| > | >> of it's type.
| > |
| > | > If it does, the program is not a valid ISO C++ program.
| > |
| > | ? What? Of course it is.
| > |
| > | I think the standard is perfectly clear in this area:
| >
| > You're quoting C99 which has a quite different semantics in this area.
| > Joe is talking about C++.
|
| While C++ is a times slightly different from C... It isn't all that
| different:
|
| 7 A value of integral type can be explicitly converted to an enumeration
| type. The value is unchanged if the integral value is within the
| range of the enumeration values (_dcl.enum_). Otherwise, the result-
| ing enumeration value is unspecified.
Let's see the example at hand.
enum E { zero = 0x00, one = 0x01 };
void test(int n)
{
enum E x;
x = (E)n;
switch (x)
{
case zero: foo(); break;
case one: bar(); break;
}
}
int main()
{
test(255);
return 0;
}
The underlying type of E needs only be an integer type large enough to
contain a data expressible with a single bit -- this is where C
differs from C++ on the issue. E.g. That integer type needs
representing only two distinc values. That is, using bool is quite a fair.
| 4 Each enumeration defines a type that is different from all other
| types. Following the closing brace of an enum-specifier, each enumer-
| ator has the type of its enumeration. Prior to the closing brace, the
| type of each enumerator is the type of its initializing value. If an
| initializer is specified for an enumerator, the initializing value has
| the same type as the expression. If no initializer is specified for
| the first enumerator, the type is an unspecified integral type. Oth-
| erwise the type is the same as the type of the initializing value of
| the preceding enumerator unless the incremented value is not repre-
| sentable in that type, in which case the type is an unspecified inte-
| gral type sufficient to contain the incremented value.
|
| 5 The underlying type of an enumeration is an integral type that can
| represent all the enumerator values defined in the enumeration. It is
| implementation-defined which integral type is used as the underlying
| type for an enumeration except that the underlying type shall not be
| larger than int unless the value of an enumerator cannot fit in an int
| or unsigned int. If the enumerator-list is empty, the underlying type
| is as if the enumeration had a single enumerator with value 0. The
| value of sizeof() applied to an enumeration type, an object of enumer-
| ation type, or an enumerator, is the value of sizeof() applied to the
| underlying type.
The bits of the standard text the most relevant to Roger's question are
http://gcc.gnu.org/ml/gcc/2004-08/msg01167.html
Those say that the sequence of statements
enum E x;
x = (E)n;
store an unspecified value in the location designated by x. It may be
0 or 1 or whatever fits, it does not matter.
| This does not make the code _not_ C++. My contention remains, calling
| the code not C++ is wrong and misleading.
Probably _not_ C++ is a bit strong, but this is not the code that we
should worry about when optimizing. Those deserve what they get.
-- Gaby
More information about the Gcc
mailing list