Array of 4 bit fields?

A

Ann O'Nymous

I want to create a union, where one element is a (32 bit) unsigned int,
and the second element is an array of 8 things, each 4 bits wide. What
is the syntax for doing so?

union name {
unsigned int foo;
unsigned :4 bar[8];
} xxx;
....
xxx.foo = 0;
xxx.bar[1] = 1;
printf ("%d\n",xxx.foo); --> produces "16"

(little endian machine)

I also want to create an array of 32 booleans each 1 bit wide.

unsigned:1 flags[32];
 
K

Keith Thompson

Ann O'Nymous said:
I want to create a union, where one element is a (32 bit) unsigned int,
and the second element is an array of 8 things, each 4 bits wide. What
is the syntax for doing so?

union name {
unsigned int foo;
unsigned :4 bar[8];
} xxx;
...
xxx.foo = 0;
xxx.bar[1] = 1;
printf ("%d\n",xxx.foo); --> produces "16"

(little endian machine)

I also want to create an array of 32 booleans each 1 bit wide.

unsigned:1 flags[32];

C doesn't support arrays of bit fields; bit fields can only be members
of structures (or unions, I suppose).

For the union, you can declare a struct with four bit fields, though
you won't be able to index them:

union name {
unsigned int foo;
struct {
unsigned bar0:4;
unsigned bar1:4;
unsigned bar2:4;
unsigned bar3:4;
} bar;
};

For the bit array, you'll just have to use shifts and masks.
 
B

Ben Pfaff

Ann O'Nymous said:
I want to create a union, where one element is a (32 bit) unsigned
int, and the second element is an array of 8 things, each 4 bits wide.

C does not allow arrays of bit-fields.
 
P

Peter Nilsson

Ann O'Nymous said:
I want to create a union, where one element is a (32 bit)
unsigned int, and the second element is an array of 8 things,
each 4 bits wide.  What is the syntax for doing so?

Why do you want to do that? If you have a 32-bit unsigned
integer, just grab the nibbles directly...

#include <stdio.h>

int main(void)
{
unsigned long u = 0xDEADBEEF;
printf(" %lx", ((u >> 28) & 0xF));
printf(" %lx", ((u >> 24) & 0xF));
printf(" %lx", ((u >> 20) & 0xF));
printf(" %lx", ((u >> 16) & 0xF));
printf(" %lx", ((u >> 12) & 0xF));
printf(" %lx", ((u >> 8) & 0xF));
printf(" %lx", ((u >> 4) & 0xF));
printf(" %lx", ((u >> 0) & 0xF));
puts("");

return 0;
}
 
A

Ann O'Nymous

Why do you want to do that? If you have a 32-bit unsigned
integer, just grab the nibbles directly...

I'm just redoing some code in another language that implements a sort of
hash function that uses an array of nibbles.
 
S

Stargazer

I'm just redoing some code in another language that implements a sort of
hash function that uses an array of nibbles.

Aside of not being addressable, bit fields are not useful for array of
nibbles because they are not allocated in any particular order (MSB to
LSB or LSB to MSB). If you reprint such a bit-field structure as
unsigned char array on several different architectures you may see
some very unexpected results.

Daniel
 
A

Ann O'Nymous

Aside of not being addressable, bit fields are not useful for array of
nibbles because they are not allocated in any particular order (MSB to
LSB or LSB to MSB). If you reprint such a bit-field structure as
unsigned char array on several different architectures you may see
some very unexpected results.

Not a big deal. It is just that:

unsigned char b[8];
nibble n[8],fun(unsigned char);
for (i=0;i<8;i++) {
n = fun(b);
}

looks a lot better than something like this:

unsigned char b[8],a[4],fun(unsigned char);
for (i=0;i<4;i++) {
a = (fun(b[2*i+1])<<4) + fun(b[2*i]);
}

where "nibble" is the nonexistent 4 bit bit field type.

The arrays of booleans will be 32 chars instead.
 
B

bart.c

Not a big deal. It is just that:

unsigned char b[8];
nibble n[8],fun(unsigned char);
for (i=0;i<8;i++) {
n = fun(b);
}

looks a lot better than something like this:

unsigned char b[8],a[4],fun(unsigned char);
for (i=0;i<4;i++) {
a = (fun(b[2*i+1])<<4) + fun(b[2*i]);
}

where "nibble" is the nonexistent 4 bit bit field type.


You might do something inbetween like this:

#include <stdio.h>

int getnibble(int *narray,int index){
return (*narray>>(index*4)) & 15;
}

void setnibble(int *narray,int index,int value){
*narray = (*narray & ~(15<<(index*4))) | (value<<(index*4));
}

int main(void){
int i;
int narray[1]={0};

for (i=0; i<8; ++i)
setnibble(&narray,i,7-i);

for (i=0; i<8; ++i)
printf("%d: %d\n",i,getnibble(&narray,i));
}

So not quite as nice as using proper indexing (and being able to directly
declare/initialise an array of nibbles), but it means the fiddly bits are
just written once.

(Note the set/get functions here need extra code if the array of nibbles
exceeds one int. Also the way nibbles are laid out in memory may not be
sequential, unless this is also taken care of in the set/get functions.

And, I think the correct term is 'nybble' but I've gone along with your
spelling..)
 
J

James Harris

Aside of not being addressable, bit fields are not useful for array of
nibbles because they are not allocated in any particular order (MSB to
LSB or LSB to MSB). If you reprint such a bit-field structure as
unsigned char array on several different architectures you may see
some very unexpected results.

Not a big deal.  It is just that:

unsigned char b[8];
nibble n[8],fun(unsigned char);
for (i=0;i<8;i++) {
   n = fun(b);

}

looks a lot better than something like this:

unsigned char b[8],a[4],fun(unsigned char);
for (i=0;i<4;i++) {
   a = (fun(b[2*i+1])<<4) + fun(b[2*i]);

}


You could write the first loop as

for (i = 0; i < 8; i++) {
nib_set(&n, i, fun(nib_get(b, i));
}

Not quite as nice as an array notation but close. Fairly standard
design principles:
- separating interface from implementation
- wrapping difficult choices

James
 
P

Peter Nilsson

Ann O'Nymous said:
It is just that:

unsigned char b[8];
nibble n[8],fun(unsigned char);
for (i=0;i<8;i++) {
   n = fun(b);
}

looks a lot better than something like this:

unsigned char b[8],a[4],fun(unsigned char);
for (i=0;i<4;i++) {
   a = (fun(b[2*i+1])<<4) + fun(b[2*i]);
}

where "nibble" is the nonexistent 4 bit bit field type.


If you do...

typedef unsigned char nibble;

....you're first loop is just fine. Is there a secondary
reason why you're trying to 'pack' the data?

If you want a 32-bit result, then use a shift register...

unsigned char b[8], fun(unsigned char);
unsigned long n;

for (n = 0, i = 0; i < 8; i++)
n = (n << 4) | (fun(b & 0xF);

The & 0xF component is redundant if fun() is guaranteed to
return nibbles only.
 

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,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top