I need to create a struct of boolean flag, like this:
struct testStruct {
bool flag1;
bool flag2;
bool flag3;
bool flag4;
bool flag5;
bool flag6;
bool flag7;
bool flag8;
bool flag9;
bool flag10;
bool flag11;
bool flag12;
bool flag13;
};
But if I do that, i print out the sizeof(), that struct and it is 13.
So i think the compile use 1 byte for each flag.
Is it possible to create a struct so that each flag uses only 1 bit.
Thank you.
Yes, read about bitfields. The syntax is the colon and the field width
after the name of the member, like
bool flag1:1;
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Thank you Victor.
I am going to follow you suggestion. If I create a class like this:
class myMask {
public:
bool flag1:1;
bool flag2:1;
bool flag3:1;
bool flag4:1;
bool flag5:1;
bool flag6:1;
bool flag7:1;
bool flag8:1;
bool flag9:1;
bool flag10:1;
bool flag11:1;
bool flag12:1;
bool flag13:1;
};
Can I set all the flag to 0 by doing this:
myMask mask;
memset(&mask, '\0', sizeof(myMask));
And can I compare if 2 masks are the same by doing this:
myMask mask1;
myMask mask2;
memcmp(&mask1, &mask2, sizeof(myMask));
Thanks.
there are two things to say:
1, you need no class, but struct, because struct is good enough to
solve it;
2, either class or struct, you could use ctor where all the bit fields
are set to 0 or any value you want.
Proper way is:
myMask mask = myMask();
>> And can I compare if 2 masks are the same by doing this:
>>
>> myMask mask1;
>> myMask mask2;
>>
>> memcmp(&mask1, &mask2, sizeof(myMask));
No, because of padding, some bits can be left uninitialized, therefore
you have to compare each field.
I am not sure if you can do this (probably not)
if(mask1 == mask2)
{
...
}
> 2, either class or struct, you could use ctor where all the bit fields
> are set to 0 or any value you want.
POD structures can not have constructors. Read here:
http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html
That will leave them undefined. Consider defining the default
constructor and the comparison operator.
>
> memset(&mask, '\0', sizeof(myMask));
>
> And can I compare if 2 masks are the same by doing this:
>
> myMask mask1;
> myMask mask2;
>
> memcmp(&mask1, &mask2, sizeof(myMask));
It is better to have the overloaded operator== in your class.
Thank you for all the help.
In my case, I have this class which only have
~200 boolean flags. I am thinking if there is a faster way to
* initialize all of them to false
* compare if 2 classes have the same values (the same set of flags are
set)
Thank you again.
try this:
struct myMask {
union {
unsigned int nMask;
struct {
bool flag1:1;
bool flag2:1;
bool flag3:1;
bool flag4:1;
bool flag5:1;
bool flag6:1;
bool flag7:1;
bool flag8:1;
bool flag9:1;
bool flag10:1;
bool flag11:1;
bool flag12:1;
bool flag13:1;
};
};
};
inline bool operator==(myMask const& rm, myMask const& lm)
{return rm.nMask == lm.nMask;};
the union will force your compiler to put all the bits into one int.
you can the set the int to 0 to clear all bits and compare the ints to
compare the masks.
Just a hint: you'll never need '/0'. just write 0. '/0' is just used
to inform the readers of your code: "hey folks, this is explicitely
meant as a char in a string". so if you want to do something weired:
int i = 20;
while (i-->'\0')
{
if (i == '/2')
{
CallSomeMessageFunc("I've reached 2!");
}
}
typo: " if (i == '/2') " should be " if (i == '\2') "
Sean
What you could do is have a static object of the same class that you'll
use as the prototype for initialising, and have the proper padding to
ensure that all data members are initialised:
struct myLargeClass {
bool blah : 1; // 1st bit
bool clah : 1; // 2nd bit
...
bool zlah : 1; // 25th bit
unsigned padding : 7; // to bring it to 32 bits total
static myLargeClass prototype;
myLargeClass() {
if (this != &prototype)
memset(this, &prototype, sizeof *this);
}
};
Statics are always zero-initialised, so 'prototype' is going to contain
all zeros. Then you can always compare objects using 'memcmp' since
there will be no uninitialised bits.
Don't forget to define 'prototype' somewhere in your implementation file.
Thank you for this great idea.
I have 2 questions:
1. Do I have to pad it to a multiple of 32?
If I have 153 bool flags, do I pad it with 25 bits? 153 - (32 * 4) =
25
2. I don't understand "what is define 'prototype' somewhere in your
implementation file"?
Isn't it already defined here:
struct myLargeClass {
//...
static myLargeClass prototype;
//...
}
Thank you.
What's wrong with "*this = prototype;"?
*Much* better actually, as the language rules forbid using memset on a
class or struct that has a constructor.
Bo Persson
No. It's up to your platform. You need to find out what the sizeof
yields for your struct with only the used flags there, and then add as
many bitfields as needed.
Essentially, you need to do
unsigned padding : ( sizeof(myLargeClass) * CHAR_BITS - Nflags );
> If I have 153 bool flags, do I pad it with 25 bits? 153 - (32 * 4) =
> 25
If your system wants to create an object with size divisible by 16, say,
you will only need to add 9...
>
> 2. I don't understand "what is define 'prototype' somewhere in your
> implementation file"?
> Isn't it already defined here:
> struct myLargeClass {
> //...
> static myLargeClass prototype;
No, here it's only *declared*. Read up on static data members.
> //...
> }
>
> Thank you.
> > > myMask mask;
> > > memset(&mask, '\0', sizeof(myMask));
> > > myMask mask1;
> > > myMask mask2;
> > > memcmp(&mask1, &mask2, sizeof(myMask));
> In my case, I have this class which only have
> ~200 boolean flags. I am thinking if there is a faster way to
> * initialize all of them to false
Faster than what? I'd expect the compiler to use the fastest
means available on the target hardware for myMask().
> * compare if 2 classes have the same values (the same set of flags are
> set)
Regretfully, there's not real way to compare the values other
than one by one. The compiler is free to introduce padding
where ever it wants. In practice, if you arrange for the total
number of bits to be a multiple of your machine's word size
(with an unsigned pad:n at the end, where n is whatever is
needed), and ensure that the added field is always 0, memcmp
will almost certainly work, even if the standard doesn't
guarantee it.
--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[...]
> > And can I compare if 2 masks are the same by doing this:
> > myMask mask1;
> > myMask mask2;
> > memcmp(&mask1, &mask2, sizeof(myMask));
> try this:
> struct myMask {
> union {
> unsigned int nMask;
> struct {
> bool flag1:1;
> bool flag2:1;
> bool flag3:1;
> bool flag4:1;
> bool flag5:1;
> bool flag6:1;
> bool flag7:1;
> bool flag8:1;
> bool flag9:1;
> bool flag10:1;
> bool flag11:1;
> bool flag12:1;
> bool flag13:1;
> };
> };
> };
> inline bool operator==(myMask const& rm, myMask const& lm)
> {return rm.nMask == lm.nMask;};
Lot's of problems with that.
-- It's not legal C++. Only unions can be anonymous, not
structs.
-- You'll almost certainly end up with undefined behavior using
it; you can't access the nMask element unless it was the
last one written to.
-- If you've written to the flags structure (which you haven't
named), the padding bits may take on any arbitrary values.
Which mean that two equal myMask may have unequald nMask.
-- For up to 16 flags, you're OK, but for more, the unsigned
may be smaller than the struct.
> the union will force your compiler to put all the bits into
> one int.
Not really.
> you can the set the int to 0 to clear all bits and compare the
> ints to compare the masks.
If the int is large enough, this will probably work *IF* he
makes sure that any unused bits in the struct are always 0.
While this works, I wonder what's wrong with 'std::bitset'
that you prefer to do it manually? (I have never used it,
so I don't know what its disadvantages are.)
> V
Schobi
Thank you for all the response on this thread.
I have 1 more question.
With this idea, I can use 'memset' to clear all the flags in the
structs.
And I can use 'memcmp' to compare flags in 2 different structs.
What can I do to 'OR' the 2 structs of flags?
I know i can do this for each flag of struct:
s1.flag1 |= s2.flag1;
s1.flag2 |= s2.flag2;
s1.flag3 |= s2.flag3;
But is there a better way?
Thank you.
You're better off just assigning from a prototype. 'memset' is
not the best solution.
> And I can use 'memcmp' to compare flags in 2 different structs.
>
> What can I do to 'OR' the 2 structs of flags?
> I know i can do this for each flag of struct:
> s1.flag1 |= s2.flag1;
> s1.flag2 |= s2.flag2;
> s1.flag3 |= s2.flag3;
>
> But is there a better way?
I don't know of any. With bitfields like you want, you will
probably have to change them manually like this. Don't yield
to the temptation to use a union. There was a suggestion to
use a bitset instead, take it into cosideration.