Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   bitfield in struct and padding (http://www.velocityreviews.com/forums/t805774-bitfield-in-struct-and-padding.html)

Stanley Rice 11-10-2011 02:29 PM

bitfield in struct and padding
 
Dear all

Here I declare a structure as follows:

struct flag
{
unsigned int a : 8; /* 1 - 7 is yield the same result*/
char b;
char c;
char d;
};

and sizeof(struct flag) equals 4, which is intuitive.

But when I make a little modification, where the bitwidth allocated to
a is 9:

struct flag
{
unsigned int a : 9; /* modification here */
char b;
char c;
char d;
};

and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
are allocated to variable a, and 3 bytes are allocated to the
following char type variable.

I want to know how many bytes are allocated to variable a? and how the
padding in the obove structure performs.

tom st denis 11-10-2011 02:40 PM

Re: bitfield in struct and padding
 
On Nov 10, 9:29*am, Stanley Rice <hecong...@gmail.com> wrote:
> Dear all
>
> Here I declare a structure as follows:
>
> struct flag
> {
> * * unsigned int * *a : 8; /* 1 - 7 is yield the same result*/
> * * char * * * * * *b;
> * * char * * * * * *c;
> * * char * * * * * *d;
>
> };
>
> and sizeof(struct flag) equals 4, which is intuitive.
>
> But when I make a little modification, where the bitwidth allocated to
> a is 9:
>
> struct flag
> {
> * * unsigned int * *a : 9; /* modification here */
> * * char * * * * * *b;
> * * char * * * * * *c;
> * * char * * * * * *d;
>
> };
>
> and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
> are allocated to variable a, and 3 bytes are allocated to the
> following char type variable.
>
> I want to know how many bytes are allocated to variable a? and how the
> padding in the obove structure performs.


That's more of a compiler question than anything. Chances are good
you're on a 32 or 64-bit host where it is optimizing the structure by
padding it out to 32-bits, then adding padding to the structure as a
whole.

There are usually [per-compiler] pragmas to be had to pack structure
densely. They're not portable.

From experience, if you are using bit-fields it's probably because

a) You're writing non-portable code that talks to hardware

or

b) You're trying to avoid having to use & operators explicitly in your
code when dealing with truncated values...

Personally I've never used bitfields in anything I've written in the
19 years I've been using C [both as an amateur and a pro]...

Tom

Ben Bacarisse 11-10-2011 02:46 PM

Re: bitfield in struct and padding
 
Stanley Rice <heconghui@gmail.com> writes:

> Here I declare a structure as follows:
>
> struct flag
> {
> unsigned int a : 8; /* 1 - 7 is yield the same result*/
> char b;
> char c;
> char d;
> };
>
> and sizeof(struct flag) equals 4, which is intuitive.
>
> But when I make a little modification, where the bitwidth allocated to
> a is 9:
>
> struct flag
> {
> unsigned int a : 9; /* modification here */
> char b;
> char c;
> char d;
> };
>
> and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
> are allocated to variable a, and 3 bytes are allocated to the
> following char type variable.
>
> I want to know how many bytes are allocated to variable a? and how the
> padding in the obove structure performs.


I don't think there is a simple way to find out. It must be more than 1
on machine with CHAR_BIT==8, but other than that all you can tell is
where 'b' is. If, say, offsetof(struct flag, b) == 4, you can't tell if
this is due to padding or the size of the unit used to hold 'a', but
does it matter?

More to the point, what is the reason you need to know? What are you
trying to achieve? If your objective is to control the layout, your
compiler may provide non-standard ways to do that. But even so, I'd
want to know the ultimate objective, because there may be better ways to
achieve it.

--
Ben.

Malcolm McLean 11-10-2011 05:20 PM

Re: bitfield in struct and padding
 
On Nov 10, 4:29*pm, Stanley Rice <hecong...@gmail.com> wrote:
> Dear all
>
> Here I declare a structure as follows:
>
> struct flag
> {
> * * unsigned int * *a : 8; /* 1 - 7 is yield the same result*/
> * * char * * * * * *b;
> * * char * * * * * *c;
> * * char * * * * * *d;
>
> };
>
> and sizeof(struct flag) equals 4, which is intuitive.
>
> But when I make a little modification, where the bitwidth allocated to
> a is 9:
>
> struct flag
> {
> * * unsigned int * *a : 9; /* modification here */
> * * char * * * * * *b;
> * * char * * * * * *c;
> * * char * * * * * *d;
>
> };
>
> and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
> are allocated to variable a, and 3 bytes are allocated to the
> following char type variable.
>
> I want to know how many bytes are allocated to variable a? and how the
> padding in the obove structure performs.
>

You can easily find out.

struct flag s;
printf("%d %d %d %d\n", (int) (&s.b - &s), (int)(&s.c - &s), (int)
(&s.d - &s), (int) sizeof(s));

That will tell you where the padding has been inserted. Clearly on any
system with 8 bit bytes you will need some padding, since 9 bits can't
fit into a whole number of bytes.



James Dow Allen 11-10-2011 06:53 PM

Re: bitfield in struct and padding
 
On Nov 10, 9:40*pm, tom st denis <t...@iahu.ca> wrote:
> From experience, if you are using bit-fields it's probably because
>
> a) You're writing non-portable code that talks to hardware, or


> b) You're trying to avoid having to use & operators explicitly in your
> code when dealing with truncated values..., [or]


and I would add
c) taking advantage, in routine(s) you want optimized for
speed, of some compilers which deliver better opcodes when
bitfield is used (True of the Sun 68k 1988 compiler;
Perhaps present-day compilers are so good,
this is no longer a problem), or

d) for better readability, e.g. to write
q->bptr = dval; /* Stmt D1 */
instead of
q->d[FADDR] = q->d[FADDR] & ~MASKFOO \
| dval << FOOSHIF; /* Stmt D2 */

> Personally I've never used bitfields in anything I've written in the
> 19 years I've been using C [both as an amateur and a pro]...
>
> Tom


I can say the same, more-or-less. It is the concern about
portability ease that often leads the coder to avoid them unless
there is a very important benefit.

Looking at my example (d) above, I consider that the first form
has a significant readability win. What do others think?

James Dow Allen

tom st denis 11-10-2011 07:17 PM

Re: bitfield in struct and padding
 
On Nov 10, 1:53*pm, James Dow Allen <jdallen2...@yahoo.com> wrote:
> On Nov 10, 9:40*pm, tom st denis <t...@iahu.ca> wrote:
>
> > From experience, if you are using bit-fields it's probably because

>
> > a) You're writing non-portable code that talks to hardware, or
> > b) You're trying to avoid having to use & operators explicitly in your
> > code when dealing with truncated values..., [or]

>
> and I would add
> c) taking advantage, in routine(s) you want optimized for
> speed, of some compilers which deliver better opcodes when
> bitfield is used (True of the Sun 68k 1988 compiler;
> Perhaps present-day compilers are so good,
> this is no longer a problem), or
>
> d) for better readability, e.g. to write
> * * q->bptr = dval; */* Stmt D1 */
> instead of
> * * q->d[FADDR] = q->d[FADDR] & ~MASKFOO \
> * * * * * * | dval << FOOSHIF; /* Stmt D2 */
>
> > Personally I've never used bitfields in anything I've written in the
> > 19 years I've been using C [both as an amateur and a pro]...

>
> > Tom

>
> I can say the same, more-or-less. *It is the concern about
> portability ease that often leads the coder to avoid them unless
> there is a very important benefit.
>
> Looking at my example (d) above, I consider that the first form
> has a significant readability win. *What do others think?


I'd use a macro....

q->d = SET_D_FIELD(potato);

or something to that effect (I write HW drivers a large part of my day
lately...).

Tom

Keith Thompson 11-10-2011 07:32 PM

Re: bitfield in struct and padding
 
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> On Nov 10, 4:29*pm, Stanley Rice <hecong...@gmail.com> wrote:
>> Here I declare a structure as follows:
>>
>> struct flag
>> {
>> * * unsigned int * *a : 8; /* 1 - 7 is yield the same result*/
>> * * char * * * * * *b;
>> * * char * * * * * *c;
>> * * char * * * * * *d;
>>
>> };
>>
>> and sizeof(struct flag) equals 4, which is intuitive.
>>
>> But when I make a little modification, where the bitwidth allocated to
>> a is 9:
>>
>> struct flag
>> {
>> * * unsigned int * *a : 9; /* modification here */
>> * * char * * * * * *b;
>> * * char * * * * * *c;
>> * * char * * * * * *d;
>>
>> };
>>
>> and sizeof(struct flag) equals 8, but not 5, where variable 2 bytes
>> are allocated to variable a, and 3 bytes are allocated to the
>> following char type variable.
>>
>> I want to know how many bytes are allocated to variable a? and how the
>> padding in the obove structure performs.
>>

> You can easily find out.
>
> struct flag s;
> printf("%d %d %d %d\n", (int) (&s.b - &s), (int)(&s.c - &s), (int)
> (&s.d - &s), (int) sizeof(s));


I don't believe that will compile. &s.b is of type char*; &s is of type
struct flag*.

Just use the offsetof() macro, defined in <stddef.h>.

Here's a program I just threw together (note that offsetof() can't be
applied to a bit-field).

#include <stdio.h>
#include <stddef.h>

struct flag7
{
unsigned int a : 7;
char b;
char c;
char d;
};

struct flag8
{
unsigned int a : 8;
char b;
char c;
char d;
};


struct flag9
{
unsigned int a : 9;
char b;
char c;
char d;
};

int main(void) {
printf("sizeof (struct flag7) = %d\n", (int)sizeof (struct flag7));
printf(" b at %d\n", (int)offsetof(struct flag7, b));
printf(" c at %d\n", (int)offsetof(struct flag7, c));
printf(" c at %d\n", (int)offsetof(struct flag7, d));

printf("sizeof (struct flag8) = %d\n", (int)sizeof (struct flag8));
printf(" b at %d\n", (int)offsetof(struct flag8, b));
printf(" c at %d\n", (int)offsetof(struct flag8, c));
printf(" c at %d\n", (int)offsetof(struct flag8, d));

printf("sizeof (struct flag9) = %d\n", (int)sizeof (struct flag9));
printf(" b at %d\n", (int)offsetof(struct flag9, b));
printf(" c at %d\n", (int)offsetof(struct flag9, c));
printf(" c at %d\n", (int)offsetof(struct flag9, d));

return 0;
}

On my system, the output is:

sizeof (struct flag7) = 4
b at 1
c at 2
c at 3
sizeof (struct flag8) = 4
b at 1
c at 2
c at 3
sizeof (struct flag9) = 8
b at 2
c at 3
c at 4

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"


All times are GMT. The time now is 10:08 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.