2

I thought that using a C bitfield instead of a int along with a bunch of #defines would give a better-to-read code and reduce the need for adapting existing code when adding new fields. Is there any possibility to reset all Bits in a C bitfield to zero with a single command as the int-#define-method provides?

Examples:

#define MYFLAG_1 0x01
#define MYFLAG_2 0x02
#define MYFLAG_3 0x04

int myflags = MYFLAG_1 | MYFLAG_3;

/* Reset: */
myflags = 0;

versus

struct {
    int flag_1 : 1;
    int flag_2 : 1;
    int flag_3 : 1;
} myflags;

myflags.flag_1 = 1;
myflags.flag_3 = 1;

/* Reset: */
myflags.flag_1 = 0;
myflags.flag_2 = 0;
myflags.flag_3 = 0;

Adding an additional flag to the field would require no change (apart from the #define) in the existing code of the first example but would require code to reset the additional flag field.

urzeit
  • 2,863
  • 20
  • 36
  • I'd have to add the new value a) to the bitfield and b) to the function. – urzeit Nov 25 '14 at 08:02
  • 3
    What about `memset(&my_flags, 0, sizeof(myflags))` – n0p Nov 25 '14 at 08:03
  • @urzeit I'm not following. You don't have to add anything. – 2501 Nov 25 '14 at 08:03
  • If I add a new flag to the `struct` I have to add it to the function, too, right? – urzeit Nov 25 '14 at 08:04
  • @Coconop: Does the standard guarantee for that to work? – urzeit Nov 25 '14 at 08:04
  • Or perhaps `*(int*)&myflags = 0;` – Cyclonecode Nov 25 '14 at 08:06
  • 1
    @Krister Andersson: That will not work if the bitfield grows beyond the size of an `int`. – urzeit Nov 25 '14 at 08:08
  • 2
    Whats about using `unions`? You could have an `UINT` or `ULONG` sharing the same memory with the bit field. Setting the number to zero will also null the bits. See http://stackoverflow.com/questions/3497345/is-there-a-way-to-access-individual-bits-with-a-union (for your use case, limited to length of the numerical variable, but up to 64bits may be sufficient) – sweber Nov 25 '14 at 08:10
  • 1
    `#define RESET(bits) memset(&bits, 0, sizeof(bits))` – Cyclonecode Nov 25 '14 at 08:17
  • 2
    @KristerAndersson I believe that (`*(int*)&myflags = 0;`) breaks the strict aliasing rule and in addition types might have different alignment restrictions. – user694733 Nov 25 '14 at 08:17
  • 1
    I don't have a standard reference to back me up on this, but I don't see any limitation for this solution in your use-case. – n0p Nov 25 '14 at 08:18
  • @user694733 - Yes that could be the case, I was thinking that the structure will be padded to 4bytes. Of course this won't work if that isn't the case or the size of the structure grows bigger then an int. – Cyclonecode Nov 25 '14 at 08:19
  • 1
    Your bitfiels are small. That's good. There is nothing to prevent you from defining a `bits_on` instance of the field and a `bits_off` instance. Then turning all on/off is a simple of `memcpy` from the one desired, or a simple `or` or `and` with the one needed. – David C. Rankin Nov 25 '14 at 08:31

2 Answers2

3

I'd like to expand my comment to an answer:

Using a union, you can have a numerical variable and your bit field sharing the same memory:

typedef  union{
    struct {
        int flag_1 : 1;
        int flag_2 : 1;
        int flag_3 : 1;
    };
    unsigned int value;
} MyBitField;

// ...
MyBitField myflags;

myflags.flag_1 = 1;
myflags.flag_3 = 1;

/* Reset: */
//myflags.flag_1 = 0;
//myflags.flag_2 = 0;
//myflags.flag_3 = 0;

myflags.value = 0;

Now, you can easily set all bits to 0. The union will always occupy the amount of memory the largest object in it needs. So, if you need more bits than an INT has, you may also use a long or long long.

I haven't seen unions in "computer programming" until now, but for microcontrollers, they are used quite often.

sweber
  • 2,916
  • 2
  • 15
  • 22
  • 1
    Should be mentioned that union aliasing is only guaranteed to work on C99 or newer. There is also possibility that bitfield and value member do not alias: Compiler is free to use larger type for bit-field, in this case it could even be `unsigned long long`. – user694733 Nov 25 '14 at 08:38
  • I once asked a similiar question regarding using a union and a struct liek this and got the answer that this is undefined behavior. allthough very likely to work – rowan.G Nov 25 '14 at 12:01
  • I like the idea of using an union - and have used it quite often. It just feels better then memset(..) - working on micro-controllers this adds too much overhead. If the bit fields go beyond an int - I can't see any reason why you can't just use an array for value - i.e int value[ 2 ]; then clear each int within it. – Neil May 06 '15 at 15:10
2

I would simply suggest:

memset(&my_flags, 0, sizeof(myflags));

This way, you can still add fields to your structure, they will be reset thanks to sizeof.

n0p
  • 3,399
  • 2
  • 29
  • 50