bit-fields and permitted types (and [OT] gcc)

C

Chris McDonald

Section 6.7.2.1(4) of the C Standard TC1 states that the type of a
bit-field (in structures) may only be a _Bool, signed int, unsigned int,
or an implementation-defined type.

I'm trying to compile some code requiring a 16-bit integer to have a
number of bit fields. I prefer to develop standards-conforming code as
much as possible, so I'm compiling with

<OT>
gcc -std=c99 -pedantic -Wall -o try try.c

With the -pedantic switch, the appended code raises a warning for Control2
because of version's type. Without -pedantic no warning is raised.
</OT>

I believe that I understand this all (please correct me if I'm wrong),
but am wondering:

- As the size of the standard types specified in Section 6.7.2.1(4) of TC1
are all architecture-dependent, why does the standard limit bit-fields
to this list of types?

- Is/has there been any discussion about permitting the integer types in
<stdint.h> to be used as bit-fields, e.g. int16_t version:2 ;

- Is it possible to write standards-conforming code when a known,
fixed-size object with bit-fields is required?

Thanks,

______________________________________________________________________________
Dr Chris McDonald E: (e-mail address removed)
Computer Science & Software Engineering W: http://www.csse.uwa.edu.au/~chris
The University of Western Australia, M002 T: +618 6488 2533
Crawley, Western Australia, 6009 F: +618 6488 1089


#include <stdio.h>
#include <stdint.h>

typedef struct {
int version :2;
} Control1;

typedef struct {
unsigned short version :2;
} Control2;

int main(int argc, char *argv[])
{
return(0);
}
 
E

Eric Sosman

Chris said:
Section 6.7.2.1(4) of the C Standard TC1 states that the type of a
bit-field (in structures) may only be a _Bool, signed int, unsigned int,
or an implementation-defined type.
[...]
I believe that I understand this all (please correct me if I'm wrong),
but am wondering:

- As the size of the standard types specified in Section 6.7.2.1(4) of TC1
are all architecture-dependent, why does the standard limit bit-fields
to this list of types?

- Is/has there been any discussion about permitting the integer types in
<stdint.h> to be used as bit-fields, e.g. int16_t version:2 ;

These two questions might be better suited to comp.std.c,
the newsgroup devoted to issues of the Standards themeselves
as opposed to the languages they define.
- Is it possible to write standards-conforming code when a known,
fixed-size object with bit-fields is required?

No (if I'm reading your question correctly). The implementation
is free to insert unnamed padding bytes after any struct element,
so you cannot be 100% sure that your struct will have the size you
require.

The usual motivation for requiring a particular size is that
you want to match the layout of the struct to some externally-
imposed format: a packet header, a record in a file, a device
control register, something of that kind. Doing so involves a
greater or lesser sacrifice of portability:

- Structs may be padded and different implementations will
pad them differently, so the exact same struct declaration
can produce different layouts on different compilers.

- The representations of the struct elements are frequently
non-portable. There are "endianness" issues, size issues
(how many bits in a `long'?), encoding issues (not all
systems use IEEE floating-point all the time), and so on.

- When manipulating device registers, it is often the case
that the registers will only respond to a subset of the
host machine's load and store instructions. For example,
a 32-bit register may react only if probed by a 32-bit
instruction; trying to access two 16-bit halves might not
work at all. But if you've cleverly mapped a struct of
bit fields onto such a register and you query one of those
fields, you can't be sure the compiler will generate the
"right" instruction.

You'll need to weigh these (and other) concerns when choosing
whether to pursue non-portable approaches or to pursue greater
portability by writing extra code. One approach that's useful
in many situations (but perhaps not with device registers) is to
map the external format to an array of `unsigned char' and write
"get" and "put" functions to translate the array to and from the
struct. You no longer need to worry about the peculiarities of
the struct layout, and the functions can also take care of issues
like representations.
 

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,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top