2 & 3 Bit Numbers

Hi,

Is it possible to save 2 & 3 bit values? I don't want to use integers, because they are to big…

I know that I can use an integer and shift the bit values to read them. It would work for the 2 bit values and I could save up to 4 numbers in a integer. But what should I do with the 3 bit values? They don't really fit in a 8 bit integer. Is there really no better way in saving 3 bit values?

Thanks1

Oh and I found this code:

   struct Cell {
      int a : 2;
      int b : 2;
      int c : 2;
      int d : 2;
   };

Would this be an abstraction of 4x two bit values for 1 integer? or would it save 4 integers.

An int is 16 bits, a byte is 8.

Your struct would work for storing 4 x 2bit variables in a byte, just remember that the compiler will use bit shifts to access them, so while it will reduce RAM consumption by a factor of 4, it will increase the time it takes to do calculations using them and increase Flash usage.

Those struct fields are called bit fields and they are exactly what you are looking for.
Use them wisely (!). Read up about unions too.

Also remember that bitfield have signedness.
In otherwords, your two bit variable declared as a signed int can take the values:
-2, -1, 0 and 1.
If you declare them as byte or unsigned int, they can take:
0,1,2 and 3

Here are some you could use for 3bit:

struct Cell {
      byte a : 3;
      byte b : 3;
      byte : 2; //empty as 3bit doesn't fit neatly.
   }; //Total size = 1byte

 struct Cell {
      byte a : 3;
      byte b : 3;
      byte c : 3;
      byte d : 3;
      byte e : 3;
      byte : 1; //empty as 3bit doesn't fit neatly.
   }; //Total size = 2bytes

 struct Cell {
      byte a : 3;
      byte b : 3;
      byte c : 3;
      byte d : 3;
      byte e : 3;
      byte f : 3;
      byte g : 3;
      byte h : 3;
   }; //Total size = 3bytes

Okay, thanks.

So If I would want to have 3 bit numbers I say:

   struct Cell {
      byte a : 3;
      byte b : 3;
   };

Two bytes would stay unused…Seems to be space waste. Any better way? :confused:

Just use the high and low nibble of a byte to store your numbers. You will need to write separate code to unpack and use them.
I think it would be much better to just save them as individual bytes. Do you really have that many of them?

flocked:
So If I would want to have 3 bit numbers I say:

   struct Cell {

byte a : 3;
     byte b : 3;
  };




Two bytes would stay unused…Seems to be space space. Any better way? :/

No you just waste 2 bits, but as the byte is the smallest addressable unit of memory, you lose no memory

flocked:
Is it possible to save 2 & 3 bit values? I don't want to use integers, because they are to big…

Save where? And how many are you planning to save?

flocked:
So If I would want to have 3 bit numbers I say:

   struct Cell {

byte a : 3;
     byte b : 3;
  };




Two bytes would stay unused…Seems to be space space. Any better way? :/

Bit fields get a bad rap sometimes because they're "implementation dependent" -- meaning the compiler can store that data any way it chooses to, including allocating dedicated integers for every field. In practice, most compilers do something sensible.

A caveat worth noting is the layout in memory is not defined, so you have to use the struct to access the values -- i.e., you can't just use e.g., memcpy and expect the data to be meaningful to another computer... Particularly important for applications that share data via files on disk or over the network. In short: The resulting memory layout is not portable, but as long as you only touch the contents via the struct interface, you're fine.

In your given case, what happens is the compiler will (probably) allocate one byte of memory, and store the two struct elements (A and B) as 3-bit fields within that one byte. This is the most (memory-) efficient way it can be done, as it is essentially the same thing as using shift operators yourself on a single byte variable, but more human-readable. Either way, 2 bits are wasted (you're only using six of the eight available). Nothing can be done about that.

Of course, if you're intending to store a finite but significant amount of 3-bit fields, you can make that struct rather large ... with elements from A to Z, for example ... and the compile will (presumably) pack the fields together into however many bytes are physically necessary to hold them all. Although, some compilers may not allow individual fields to span across whatever native allocation boundary it uses -- possibly 8-bits, or 16, or 32, 64... So you may end up wasting 2 bits for every 6, or 1 bit every 15, etc...

flocked:
Is it possible to save 2 & 3 bit values? I don’t want to use integers, because they are to big…

Use a char or byte then.

How many of these are you planning to have? Sounds like a lot of work unless you have hundreds of them.

can you make arrays of those bitfields? // popped up suddenly

something like

Struct cell
{
int b[4] : 8
}

(OK I can test sketch this :slight_smile:

If you really want to store data in 3 bit chunks, you can do it in a RAM efficient way by bit twiddling operations - declare an array of unsigned char that has enough bits in it to store what you need. Then it's a (fairly) easy matter of coding read and write accessor functions to get/set the nth set of 3 bits.

The question remains though - why do you need to do this?

because it can be done?
exploring the limits of what is possible is one of humans biggest driving forces.

I was trying to find Raymond Chen's remark about what kind of nails do you use for Balsa wood, but this was as close as I got:

Starts off with:

A common obstacle when trying to help people solve their problems is that what people ask for and what they actually want are not always the same thing.

Not always true of course, but it's certainly seen here often enough - hence the query :slight_smile:

robtillaart:
because it can be done?
exploring the limits of what is possible is one of humans biggest driving forces.

True, but the appropriate way to save data depends entirely on what data is being stored and what constraints need to be met - if this is only an academic exercise then the data can be stored however you want, but if this is an attempt to solve a real problem then we need much more information about the problem before we can advise how best to solve it.

robtillaart:
can you make arrays of those bitfields? // popped up suddenly

something like

Struct cell
{
int b[4] : 8
}

(OK I can test sketch this :slight_smile:

No, you can't. If you think about it, pointers can only point to whole memory addresses, so what would be the pointer to each element in that bitfield look like?
Have a look here for a better description of why:

thanks, pointer math is the culprit

robtillaart:
can you make arrays of those bitfields? // popped up suddenly
something like

Struct cell

{
  int b[4] : 8
}



(OK I can test sketch this :)

No, this is illegal. You can only make arrays of things you can take the address of, and you can’t take the address of bit fields.

You could define a struct which holds a number of bitfields which fit into a convenient number of bytes, and define an array of those. (With a layer of indirection, you could make the result ‘array of bitfield sets’ behave conceptually as though they were in a simple array.)

robtillaart:
because it can be done?
exploring the limits of what is possible is one of humans biggest driving forces.

I'm not opposed to that, of course. It is always interesting to find new things.

However in the context of the forum, we often get queries like "how do I break out of an interrupt and go back to the start of loop?", when the problem really is a misunderstanding of what an interrupt is for.

I'm assuming that the real problem is not how to compress two bits into some sort of "2-bit int" but really to make some code fit into the available memory. A deeper analysis might reveal, for example, that those 2 bits aren't even required in the first place.