views:

133

answers:

3

I noticed while making a program that a lot of my int type variables never went above ten. I figure that because an int is 2 bytes at the shortest (1 if you count char), so I should be able to store 4 unsigned ints with a max value of 15 in a short int, and I know I can access each one individually using >> and <<:

short unsigned int SLWD = 11434;
S is (SLWD >> 12), L is ((SLWD << 4) >> 12),
W is ((SLWD << 8) >> 12), and D is ((SLWD << 8) >> 12)

However, I have no idea how to encompase this in a function of class, since any type of GetVal() function would have to be of type int, which defeats the purpose of isolating the bits in the first place.

+1  A: 

That's a very common technique. You usually allocate an array of the larger primitive type (e.g., ints or longs), and have some abstraction to deal with the mapping. If you're using an OO language, it's usually a good idea to actually define some sort of BitArray or SmartArray or something like that, and impement a getVal() that takes an index. The important thing is to make sure you hide the details of the internal representation (e.g., for when you move between platforms).

That being said, most mainstream languages already have this functionality available.
If you just want bits, WikiPedia has a good list. If you want more than bits, you can still find something, or implement it yourself with a similar interface. Take a look at the Java BitSet for reference

Uri
"The important thing is to make sure you hide the details of the internal representation (e.g., for when you move between platforms)." Portability may not be important, access speed may be more important.
Justicle
+4  A: 

First, remember the Rules of Optimization. But this is possible in C or C++ using bitfields:

struct mystruct {
    unsigned int smallint1 : 3; /* 3 bits wide, values  0 -- 7 */
    signed int   smallint2 : 4; /* 4 bits wide, values -8 -- 7 */
    unsigned int boolean   : 1; /* 1 bit  wide, values  0 -- 1 */
};

It's worth noting that while you gain by not requiring so much storage, you lose because it becomes more costly to access everything, since each read or write now has a bunch of bit twiddling mechanics associated with it. Given that storage is cheap, it's probably not worth it.

Edit: You can also use vector<bool> to store 1-bit bools; but beware of it because it doesn't act like a normal vector! In particular, it doesn't provide iterators. It's sufficiently different that it's fair to say a vector<bool> is not actually a vector. Scott Meyers wrote very clearly on this topic in 'Effective STL'.

Philip Potter
I suppose that the only time it'd actually be useful is if I literally had hundreds values being used simlutaneously. But it is nice to know I can make a bool thats actually only 1 bit. ^^
Keand64
talking about 1-bit bools reminded me of vector<bool>, see edited answer.
Philip Potter
Hundreds of values will still only save you hundreds or thousands of bytes... you need to be talking tens or hundreds of thousands of instances for this to start to matter a lot. (Of course there are many cases where you do have that many instances...)
Michael Anderson
sizeof(mystruct) is 4 on my compiler. Beware of struct padding.
Justicle
@Justicle: +1 Good point. The padding kills all the savings. The answer is to pack more values into the struct so it's 32 or 64 bits wide (depending on implementation).
Philip Potter
`int smallint2 : 4;` is ambiguous; you need to specify `signed int smallint2 : 4;` to be sure it can hold negative values.
Potatoswatter
Per @Justicle's point, the compiler is likely to pad the structure to align to the largest declared native type, regardless of bitfields. So replacing `int` with `char` here will likely restore its size to 1 byte. (On the flip side, the compiler may get finicky if you give them *different* types, so you're best off declaring all your bitfields with the type with the desired final alignment rather than minimizing each individual declaration.)
Potatoswatter
@Potatoswatter: thanks, will edit.
Philip Potter
+2  A: 

In C, and for the sole purpose of saving space, you can reinterpret the unsigned short as a structure with bitfields (or use such structure without messing with reinterpretations):

#include <stdio.h>

typedef struct bf_
{
   unsigned  x : 4;
   unsigned  y : 4;
   unsigned  z : 4;
   unsigned  w : 4;
} bf;


int main(void)
{
   unsigned short i = 5;
   bf *bitfields = (bf *) &i;

   bitfields->w = 12;
   printf("%d\n", bitfields->x);
   // etc..

   return 0;
}
Federico Ramponi
+1, I didn't know of this syntax :)
Chris Dennett
sizeof(bf) is 4 on my compiler. Beware of struct padding.
Justicle
+1, same as Chris. That could be incredibly powerful. If only there were favourite answers...
Ninefingers
Justicle: you're right. Better to go for structs with the same size of a word (in our case, 32 bit).
Federico Ramponi