Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to define 2 bit variable

68 views
Skip to first unread message

Adnan Rashid

unread,
Jun 2, 2020, 8:08:39 AM6/2/20
to
Hi All,

I want to declare a variable that holds only 2 bits.

In my problem, I have possible combinations are

00
01
10
11

so bool and integer type not required. Thanks in advance

Bonita Montero

unread,
Jun 2, 2020, 8:44:48 AM6/2/20
to
struct
{
unsigned value : 2;
} s;
You can't define bitfields out of a struct.

Jorgen Grahn

unread,
Jun 2, 2020, 9:10:48 AM6/2/20
to
Depends on what you want to do with it. One solution is

enum class Bits { Zero, One, Two, Three };

but that won't, I think, be more compact in memory than

struct Bits {
Bits(bool a, bool b);
private:
unsigned char bits;
};

and not a lot more compact than

std::pair<bool, bool>

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Nikolaj Lazic

unread,
Jun 2, 2020, 9:25:13 AM6/2/20
to
Dana Tue, 2 Jun 2020 05:08:24 -0700 (PDT), Adnan Rashid <adnanr...@gmail.com> napis'o:
Minimal storage size is char or byte. If you want to store 1 bit you have to
allocate 1 byte at least.

Bart

unread,
Jun 2, 2020, 9:57:05 AM6/2/20
to
Implementations typically allow such variables of 8 to 64 bits.

Most applications will only need some of the 2**8 to 2**64 possible
values; they just ignore the rest.

How many 2-bit variables will there be in total? If only one, then the
packing/unpacking code needed will far exceed the 6 bits saved from uint8_t.

James Kuyper

unread,
Jun 2, 2020, 10:09:48 AM6/2/20
to
You can declare such a field, but only inside a struct. It's called a
bit-field:

struct contains_two_bit{
unsigned char two_bit:2;
};

However, while two_bit itself takes up only two bits, the entire struct
necessarily takes up at least one entire byte, and might take up more
space than that. You don't save any actual space by defining such a type
unless you declare other bit-fields either immediately before or
immediately after that one, in which case it may use up less space than
if you declared them as non-bit-fields. Adjacent bit-fields are packed
into some addressable allocation unit, the size of which depends upon
the implementation. The order of those bit-fields within an allocation
unit also varies with the implementation. Whether or not a bit-field
that is smaller than the allocation unit size may straddle the boundary
between allocation units can also vary from one implementation to
another. For example, given

struct bit_fields {
bool a:1;
int8_t b:3;
int8_t c:5;
int8_t d:7;
int16_t e:11;
int16_t f:13;
}

An implementation that uses an allocation unit with a size of 8, which
allows bit fields to straddle allocation units, could implement that
type by storing the fields as follows:

byte 1: a, b, and the first four bits of c
byte 2: the last bit of c, and d
byte 3: the first 8 bits of e
byte 4: the last 3 bits of e, the first five bits of f
byte 5: the last 8 bits of e.

An implementation that uses an allocation unit with a size of 16 that
doesn't allow straddling could implement it as follows:

first 2 bytes: a, b, c d
next 2 bytes: e and 5 padding bits
last 2 bytes: f and 3 padding bits

You can't take the address of a bit-field, and you can't bind it to a
reference. If two bit-fields in a struct are separated from each other
only by other bit-fields, you cannot safely access both bit fields
concurrently. For these reasons, it's often not worthwhile to declare
things as bit-fields.

Bonita Montero

unread,
Jun 2, 2020, 12:00:21 PM6/2/20
to
> std::pair<bool, bool>

This never would be 2 bits large.

Öö Tiib

unread,
Jun 2, 2020, 4:39:11 PM6/2/20
to
Basically others have already answered what you can do.
You can only have two bit variables as class bit-field members.
Classes will occupy at least one byte so there will be
some leftover space if you need only one such variable.
If you happen to need 4 such variables then you can easily
have it. I write some code to illustrate potential
issues that you may face:

#include <iostream>

// use unsigned to not waste time on negatives
// use chars as smallest to not have whole
// struct made larger than 1 char
struct X
{
unsigned char a:2;
unsigned char b:2;
unsigned char c:2;
unsigned char d:2;
};

int main()
{
X x {0,1,2,3};

// have to cast to unsigned since chars will be put
// out as characters not numbers by cout
std::cout << "x.a = " << (unsigned)x.a << '\n'
<< "x.b = " << (unsigned)x.b << '\n'
<< "x.c = " << (unsigned)x.c << '\n'
<< "x.d = " << (unsigned)x.d << '\n'
<< "sizeof(x) = " << sizeof(x) << '\n';

return 0;
}

I can not find a platform where that compiles but does
not output:

x.a = 0
x.b = 1
x.c = 2
x.d = 3
sizeof(x) = 1

So the 4 bit-field data members took 2 bits each and together
one byte.

Bonita Montero

unread,
Jun 4, 2020, 12:11:41 PM6/4/20
to
> In C++, there is »::std::vector< bool >« which is neither
> a vector nor does it contain bool objects. You could use
> this as a kind of an array of single bits and do the
> combining of pairs of two bits yourself.

Very inefficient !

Bo Persson

unread,
Jun 4, 2020, 1:25:37 PM6/4/20
to
It's space efficient. Sometimes that is what's needed.


Bonita Montero

unread,
Jun 4, 2020, 1:42:39 PM6/4/20
to
>> Very inefficient !

> It's space efficient. Sometimes that is what's needed.

The OP just asked for 2 bits.

Bart

unread,
Jun 4, 2020, 1:50:01 PM6/4/20
to
On 02/06/2020 22:21, Stefan Ram wrote:
> If you only need a few of those bit pairs, you have no
> memory concerns and can use one or even two int objects
> to store two bits without hesitation.
>
> If you need a lot of those bit pairs, try to hold them in
> some kind of array. Then you can pack s * CHAR_BIT bits in
> an object of size s. Bit pair p then resides at the array
> offset 2 * p /( s * CHAR_BIT ) and the object offset 2 * p
> % ( s * CHAR_BIT ), and you can use the operators "&", "|",
> ">>", "<<", and "=" to read/write a pair of bits.
>
> In a real programming language like Pascal, you can simply
> write
>
> packed array[ 1..n ]of( s00, s01, s10, s11 )
>
> or omit "packed" and let the compiler do the detail work.
>
> In C++, there is »::std::vector< bool >« which is neither
> a vector nor does it contain bool objects. You could use
> this as a kind of an array of single bits and do the
> combining of pairs of two bits yourself.

One of my languages (dynamic not static yet) allows arrays of 1, 2 and 4
bits (a natural extension, at the small end, to the sequence 8, 16, 32,
64 bits).

A 100M-element array of 2 bits (an unsigned type called 'bit2' or 'u2')
occupies 25MB (plus some loose change for the descriptors). It is
indexed and sliced as any normal array. Bounds can be N-based not just
0-based.

I got the impression such a thing is routine to add in C++ if it is not
already in some library.

James Kuyper

unread,
Jun 4, 2020, 2:17:40 PM6/4/20
to
Also, what the standard says about std::vector<bool> is somewhat
different from what it says about std::vector<T> for generic T. Those
differences allow std::vector<bool> to be implemented using bit-wise
operators (&, |, ^, ~, <<, and >>) and inline functions which would
allow code using std::vector<bool> to be optimized to be comparable in
speed to hand-optimized code using bit-wise operators directly.

Keith Thompson

unread,
Jun 4, 2020, 3:01:15 PM6/4/20
to
It's too late to change it now, but I wonder if it might have made more
sense to treat std::vector<bool> like a vector of anything else, and add
a distinct type, say std::vector_bool, that has the special behavior.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Öö Tiib

unread,
Jun 4, 2020, 4:44:15 PM6/4/20
to
On Thursday, 4 June 2020 22:01:15 UTC+3, Keith Thompson wrote:
> James Kuyper <james...@alumni.caltech.edu> writes:
> > On 6/4/20 1:25 PM, Bo Persson wrote:
> >> On 2020-06-04 at 18:11, Bonita Montero wrote:
> >>>>    In C++, there is »::std::vector< bool >« which is neither
> >>>>    a vector nor does it contain bool objects. You could use
> >>>>    this as a kind of an array of single bits and do the
> >>>>    combining of pairs of two bits yourself.
> >>>
> >>> Very inefficient !
> >>
> >> It's space efficient. Sometimes that is what's needed.
> >
> > Also, what the standard says about std::vector<bool> is somewhat
> > different from what it says about std::vector<T> for generic T. Those
> > differences allow std::vector<bool> to be implemented using bit-wise
> > operators (&, |, ^, ~, <<, and >>) and inline functions which would
> > allow code using std::vector<bool> to be optimized to be comparable in
> > speed to hand-optimized code using bit-wise operators directly.
>
> It's too late to change it now, but I wonder if it might have made more
> sense to treat std::vector<bool> like a vector of anything else, and add
> a distinct type, say std::vector_bool, that has the special behavior.

The issue #96 "vector<bool> is not a container" is AFAIK still open
and proposed was std::bit_vector ... but it sort of hangs there.

Meanwhile there are also boost::dynamic_bitset in Boost,
Qt::QBitArray in QT ... bm::bvector in BitMagic and so on.

Issue with those seems to be that when we are desperate to go for
single bits then we likely also want to squeeze the performance
of our specific use-case to max ... and do not care how generic
and flexible it is for different usages.

Paavo Helde

unread,
Jun 4, 2020, 4:51:02 PM6/4/20
to
04.06.2020 22:01 Keith Thompson kirjutas:
> It's too late to change it now, but I wonder if it might have made more
> sense to treat std::vector<bool> like a vector of anything else, and add
> a distinct type, say std::vector_bool, that has the special behavior.
>

Yes, of course, std::bitvector or whatever. std::vector<bool> is a clear
example of trying to be too smart for no reason. Been there, done that
(many times, unfortunately).

Öö Tiib

unread,
Jun 4, 2020, 5:14:04 PM6/4/20
to
On Thursday, 4 June 2020 23:44:15 UTC+3, Öö Tiib wrote:
> The issue #96 "vector<bool> is not a container" is AFAIK still open
> and proposed was std::bit_vector ... but it sort of hangs there.

I was wrong ... it is NAD (not a defect), upgraded to
N2050 and N2160
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2050.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2160.html

So it is not "hanging", but "evolving".

Keith Thompson

unread,
Jun 4, 2020, 7:17:05 PM6/4/20
to
Yes, std::bitvector is a much better name than std::vector_bool.
(std::bitset already exists but isn't the same thing.)

Jorgen Grahn

unread,
Jun 5, 2020, 1:47:40 AM6/5/20
to
On Tue, 2020-06-02, Bonita Montero wrote:

> [I wrote]

>> std::pair<bool, bool>
>
> This never would be 2 bits large.

Like I indicated in the part you snipped. But the OP never explicitly
asked for that, and never AFAICT came back with more information.

You can't answer the question "how to define 2 bit variable" without
knowing its purpose, and /that's/ what we should have told the OP.

Juha Nieminen

unread,
Jun 5, 2020, 5:26:43 AM6/5/20
to
It's space efficient only when you need a lot of bits (I'd say at a very
minimum in the hundreds).

If you know at compile time the number of bits you need, then
std::bitset is much more efficient and better than std::vector<bool>.

Sal LO

unread,
Jun 10, 2020, 12:59:16 PM6/10/20
to
0 new messages