My pb concerns the sizeof of a bitfield struct, all
work fine with Borland C++ (4.52), we are moving recently
to VC++ 6, and are finding strange things with this one,
for exemple:
typedef struct
{
BYTE a : 1 ;
BYTE b : 1 ;
BYTE c : 7 ;
BYTE d : 7 ;
} my_bitf ;
With VC++6, sizeof(my_bitf) give 3 and not 2 as we expected.
We think this should be a bug in VC++, and we've send a bug report
to Microsoft, 2 weeks passed, silence...
--
Jean
BYTE is a 'unsigned char'. That means bits are padded out to 'char'
boundaries if they don't all fit in one.
typedef struct
BYTE a : 1 ; <-- fits in first char
BYTE b : 1 ; <-- fits in first char
BYTE c : 7 ; <-- first char would be 9 bits - moved to second
char
BYTE d : 7 ; <-- second char would be 14 bits - moved to third
char
} my_bitf ;
All this behavior has been defined for years by the Standards for
the C languages. MS's "silence" can be interpreted as "RTFM".
The fix is to make BYTE into an 'unsigned short' or 'WORD'. That
would let many bits fit in one 16-bit object, which is what you
need.
--
Phlip at politizen dot com (address munged)
======= http://users.deltanet.com/~tegan/home.html =======
-- The first few lines of code must "hook" the
computer, and make it "care" about the program --
Andreas
Jean Fan wrote:
>
> Hi everyone, I'm new to the list, so excuse me if this
> issue is already known and treated.
>
> My pb concerns the sizeof of a bitfield struct, all
> work fine with Borland C++ (4.52), we are moving recently
> to VC++ 6, and are finding strange things with this one,
> for exemple:
>
> typedef struct
> {
> BYTE a : 1 ;
> BYTE b : 1 ;
> BYTE c : 7 ;
> BYTE d : 7 ;
> } my_bitf ;
>
> With VC++6, sizeof(my_bitf) give 3 and not 2 as we expected.
> We think this should be a bug in VC++, and we've send a bug report
> to Microsoft, 2 weeks passed, silence...
>
> --
> Jean
: Jean Fan wrote:
:
: > typedef struct
: > {
: > BYTE a : 1 ;
: > BYTE b : 1 ;
: > BYTE c : 7 ;
: > BYTE d : 7 ;
: > } my_bitf ;
: >
: > With VC++6, sizeof(my_bitf) give 3 and not 2 as we expected.
: > We think this should be a bug in VC++, and we've send a bug report
: > to Microsoft, 2 weeks passed, silence...
:
: BYTE is a 'unsigned char'. That means bits are padded out to 'char'
: boundaries if they don't all fit in one.
: ...
: All this behavior has been defined for years by the Standards for
: the C languages. MS's "silence" can be interpreted as "RTFM".
TFM (i.e. the ISO standard) says very little about how bitfields
should be laid out. Each field could require 200K, or there might be
no padding at all. IIRC, the fields needn't even appear in lexical
order. Also, unsigned char isn't a valid type for a bitfield anyway -
VC supports that as an extension. (/W4 will warn about it).
--
Mathew Hendry, Programmer, Visual Sciences Ltd.
Work <ma...@vissci.com>, Home <sca...@dial.pipex.com>
IRC/ICQ/Q2/... "Scampi", ICQ 24839718
PGP B3C1 1EBC 2BAE 93F0 54C1 E0E7 5FA3 5988 BBD6 B689
Jean Fan wrote:
>
> Hi everyone, I'm new to the list, so excuse me if this
> issue is already known and treated.
>
> My pb concerns the sizeof of a bitfield struct, all
> work fine with Borland C++ (4.52), we are moving recently
> to VC++ 6, and are finding strange things with this one,
> for exemple:
>
> typedef struct
> {
> BYTE a : 1 ;
> BYTE b : 1 ;
> BYTE c : 7 ;
> BYTE d : 7 ;
> } my_bitf ;
>
> With VC++6, sizeof(my_bitf) give 3 and not 2 as we expected.
> We think this should be a bug in VC++, and we've send a bug report
> to Microsoft, 2 weeks passed, silence...
Bitfields are implementation-dependent and highly non-portable. If you
upgraded to BC5, I suspect your code would also not work. I would
recommend not using them.
Thanks a lot, it works with WORD.
But I don't understand why it dosen't work with BYTE,
your explication is not very clear for me.
J. Wesley Cleveland wrote
> Bitfields are implementation-dependent and highly non-portable. If you
> upgraded to BC5, I suspect your code would also not work. I would
> recommend not using them.
With BC5, no problem, sizeof(my_bitf) = 2 !
For me, the behavior in VC, if it's not a bug, it's in any way
not expected regarding the following text extracted from the official
MSDN in VC6 (C Bit Fields), see especially the example in the end,
excuse me for the long text.
Would you always say it's not a bug ?
***************************************************** Extracted from VC
6 MSDN
C Bit Fields
In addition to declarators for members of a structure or union,
a structure declarator can also be a specified number of bits,
called a bit field. Its length is set off from the declarator
for the field name by a colon. A bit field is interpreted as an
integral type.
Syntax
struct-declarator :
declarator
type-specifier declarator opt : constant-expression
The constant-expression specifies the width of the field in bits.
The type-specifier for the declarator must be unsigned int, signed int,
or int, and the constant-expression must be a nonnegative integer value.
If the value is zero, the declaration has no declarator.
Arrays of bit fields, pointers to bit fields, and functions returning
bit fields are not allowed. The optional declarator names the bit field.
Bit fields can only be declared as part of a structure. The address-of
operator (&) cannot be applied to bit-field components.
Unnamed bit fields cannot be referenced, and their contents at run time
are unpredictable. They can be used as dummy fields, for alignment
purposes.
An unnamed bit field whose width is specified as 0 guarantees that
storage
for the member following it in the struct-declaration-list begins on an
int boundary.
Bit fields must also be long enough to contain the bit pattern.
For example, these two statements are not legal:
short a:17; /* Illegal! */
int long y:33; /* Illegal! */
This example defines a two-dimensional array of structures named screen.
struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];
The array contains 2,000 elements. Each element is an individual
structure
containing four bit-field members: icon, color, underline, and blink.
The size of each structure is two bytes.
Bit fields have the same semantics as the integer type.
This means a bit field is used in expressions in exactly the same way as
a
variable of the same base type would be used, regardless of how many
bits
are in the bit field.
Microsoft Specific :
Bit fields defined as int are treated as signed. A Microsoft extension
to the
ANSI C standard allows char and long types (both signed and unsigned)
for bit
fields. Unnamed bit fields with base type long, short, or char (signed
or unsigned)
force alignment to a boundary appropriate to the base type.
Bit fields are allocated within an integer from least-significant to
most-significant bit. In the following code
struct mybitfields
{
unsigned short a : 4;
unsigned short b : 5;
unsigned short c : 7;
} test;
void main( void );
{
test.a = 2;
test.b = 31;
test.c = 0;
}
the bits would be arranged as follows:
00000001 11110010
cccccccb bbbbaaaa
Since the 8086 family of processors stores the low byte of integer
values before the high byte, the integer 0x01F2 above would be stored
in physical memory as 0xF2 followed by 0x01.
END Microsoft Specific
*************************************************** END Extracted from
VC 6 MSDN
--
Jean
____________________________________________________
Nous apprenons la geologie le matin apres le seisme.
--
Lao FAN
____________________________________________________
Nous apprenons la geologie le matin apres le seisme.
Yes, because all your bits can fit within a WORD. They can't all fit
within a BYTE.
using BYTE: the storage would look like this
BYTE a : 1; // storage now looks like this 00000001
BYTE b : 1; // storage now looks like this 00000011 (notice that
there are only 6 unused bits left in the BYTE)
BYTE c : 7; // 7 is to large to fit within the remaining 6 bits, and
since bitfields cannot span multiple storage types, it moves it to the
next BYTE 01111111 (note only 1 remaining bit)
BYTE d : 7; // Again, since there is only one remaining bit, it moves
it to the third BYTE.
If you want to optimize this, you should declare them as:
BYTE a : 1; // storage now looks like this 00000001 (note 7
remaining bits)
BYTE c : 7; // 7 is large enough to fit into the remaining bits of
byte 1, so it still takes 1 byte
BYTE b : 1; // 1 bit allocated in byte 2
BYTE d : 7; // 7 is large enough to fit into the remaining bits of
byte 2, so all 4 fields take 2 bytes
> With BC5, no problem, sizeof(my_bitf) = 2 !
you're defining it the same way?
> For me, the behavior in VC, if it's not a bug, it's in any way
> not expected regarding the following text extracted from the
official
> MSDN in VC6 (C Bit Fields), see especially the example in the end,
> excuse me for the long text.
The text show specifically how this works. (see below)
> Would you always say it's not a bug ?
No.
> short a:17; /* Illegal! */
This shows that bitfields cannot span multiple storage types.
> struct
> {
> unsigned short icon : 8;
> unsigned short color : 4;
> unsigned short underline : 1;
> unsigned short blink : 1;
> } screen[25][80];
They all fit in one short, since a short is one storage type and all
the bits add up to less than one type. No boundaries are crossed.
perhaps you can point to the specific paragraph which you think
contradicts this.
>Hi everyone, I'm new to the list, so excuse me if this
>issue is already known and treated.
>
>My pb concerns the sizeof of a bitfield struct, all
>work fine with Borland C++ (4.52), we are moving recently
>to VC++ 6, and are finding strange things with this one,
>for exemple:
>
>typedef struct
>{
> BYTE a : 1 ;
> BYTE b : 1 ;
> BYTE c : 7 ;
> BYTE d : 7 ;
>} my_bitf ;
>
>With VC++6, sizeof(my_bitf) give 3 and not 2 as we expected.
>We think this should be a bug in VC++, and we've send a bug report
>to Microsoft, 2 weeks passed, silence...
In general, you won't get a reply to a bug report filed via the web form at:
http://support.microsoft.com/support/visualc/report/default.asp
They'll look at it, but you won't get any confirmation. You might want to
use one of your free support incidents, if this is important enough to you.
See Help->Technical Support for more.
But this is not a bug. Much bitfield behavior is implementation-defined, and
above, you're expecting that bitfields can cross storage boundaries. While a
and b can fit in a BYTE, c cannot fit in that same BYTE, so c is stored in a
separate byte. Ditto for d. This is fine by the C and C++ standards, and
this explains why sizeo(my_bitf) is 3 in VC++. You should be able to work
around this problem by declaring all the members as unsigned short int.
--
Doug Harrison
dHar...@worldnet.att.net
Visual C++ MVP
After reading carefully the answers, I want to conclude
that the pb I've experienced is not a bug in VC,
but it's due to a fundamental difference between BC and VC
in the implementation of bitfields structure.
--------------------------------------------------------------
In BC, the type (char, BYTE, short, int, ...)
of the bit fields in a structure dosen't affect
the storage allocation scheme of the structure :
the bits mapping the first field to the last field
are simply arranged from position 0 to n-1,
where n is the sum of the width of all bitfields
in the structure.
So there's no consideration of "boundary alignment" AND
you can mix different types of bitfields in a
structure without any problem.
No surprise : the size of the structure = n/8 + (n%8)?1:0.
For me, this is a very clear, direct and logical
implementation for bitfields, anyone can understand it !
More, it's relatively portable : the passage of 16 bits
=> 32 bits or 32 bits => 64 bits don't change anything
to the memory scheme.
--------------------------------------------------------------
In VC, it's another story.
The logic would to say that a bitfield structure is based
on an "underlying type", which is the greatest size type
of all the bit fields defined in the structure, AND there
will be a "boundary alignment" of the fields on this
underlying type.
A very strange logic for me. I don't love it at all !
I want to point 2 defects with this implementation.
1. It's not portable (16bits => 32bits or 32bits =>64 bits).
For example:
typedef struct
{
unsigned int A : 3 ;
unsigned int B : 9 ;
unsigned int C : 5 ;
} a_bitf ; // will give different scheme in VC 16 bits & 32 bits !
2. Mix different types in a bitfields structure is problematic.
A little stupid example:
typedef struct
{
WORD a : 1 ;
BYTE b : 1 ;
} my_bitf2 ;
VC6 : sizeof(my_bitf2) = 4.
BC4 & BC5 : sizeof(my_bitf2) = 1.
--------------------------------------------------------------
Further questions:
1. I'm curious to know how the bitfields is implemented in
other C/C++ compilers (watcom c, gnu c, etc.), any idea ?
2. There's no standard, OK, but do you think the VC's implement
is logical and simple to use ?
Cheers.
Why? Well, think of it this way. Suppose you have a structure that
you've written to a data file. Then you take that data and want to
read it back using a program compiled with a different compiler (or
even different language, such as VB or Java).
Using the VC method, you can use integral data types to simulate
bitfields using logical operations to extract the data. If BC lays
out the data in a non-intregral type fashion, it becomes more
problematic.
Jean Fan <xiao.ga...@libertysurf.fr> wrote in message
news:381F5AF...@libertysurf.fr...
Chris
Erik Funkenbusch wrote in message <#zJVmoYJ$GA.228@cppssbbsa05>...