Question about creating a struct of flags in c++

P

Plissken.s

Is there an efficient way to create a struct of flag in C++?

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.
 
P

Plissken.s

Yes, read about bitfields.  The syntax is the colon and the field width
after the name of the member, like

     bool flag1:1;

V

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.
 
H

Hisense

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.
 
A

anon

Proper way is:

myMask mask = 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
 
J

James Kanze

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.
 
P

Plissken.s

[..]  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;

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.

V

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.
 
R

.rhavin grobert

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));

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!");
}
}
 
R

.rhavin grobert

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') "
 
P

Plissken.s

(e-mail address removed) wrote:
[..]  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;
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.
V
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.

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.

V

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.
 
J

Juha Nieminen

Victor said:
static myLargeClass prototype;
myLargeClass() {
if (this != &prototype)
memset(this, &prototype, sizeof *this);

What's wrong with "*this = prototype;"?
 
B

Bo Persson

Juha said:
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
 
J

James Kanze

[..] 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;
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.
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.
 
J

James Kanze

On 30 Okt., 06:50, "(e-mail address removed)" <[email protected]>
wrote:

[...]
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.
 
P

Plissken.s

(e-mail address removed) wrote:
[..]  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;
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.
V
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.

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.

V

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.
 

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,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top