3

In my program I have a C bit-field structure as:

 typedef struct
 {
    char a:1;
    char b:1;
    char c:1;
    char d:1;
 }_OpModes;
 _OpModes Operation; 

Now I want to check at least one of the flags is set in the above structure, If so do some operation otherwise return.

Though I can do this by checking bit by bit, that will be processor intensive for my Embedded application as structure of flags is big enough. I am looking for some operations such as (operation & 0xFF) to detect.

So can anyone suggest how to do this in C??

jww
  • 97,681
  • 90
  • 411
  • 885
  • avoid bitfields at all costs, they cause nothing but pain, you are not saving anything (well maybe some typing) by using them. Using masks and shifts you can gain the same number of instructions, etc. And once you do that then masking groups of them are even easier because you know the location of each of the items in the group and you have an access method (something you dont get with bitfields even if using a union) – old_timer Nov 09 '16 at 22:05
  • 1
    Also be careful... The valid values for 1 bit are 0 and -1 because its usually (always?) 2's compliment taking up 1 bit. If you try `OpModes.a == 1`, then it will always fail or appear off or low. I've seen it produce some very nasty, hard to track down bugs. – jww Nov 09 '16 at 22:06
  • if you go with the union approach then it can work but is very compiler specific, you basically have to re-check the code every time you use a different compiler and or version and or command lines, or make the code try to detect (and of course it is an illegal use of unions anyway). – old_timer Nov 09 '16 at 22:07
  • @dwelch: "avoid bitfields at all costs"? No, really. – AnT stands with Russia Nov 09 '16 at 22:09
  • I don't think there is any easy/portable way to do this with bitfields. But if `_OpModes` was just a `char` or `uint8_t`, then it would be as simple as masking off the uninteresting bits with the bitwise-AND operator and then comparing the result with zero. – kkrambo Nov 09 '16 at 22:11
  • It is implementation-defined whether bitfields can be declared as type `char` at all. If they can be declared that way, the only standard-defined significance of doing so is its effect on the type of lvalues designating such bitfields -- in particular, the standard makes no connection between bitfields' declared types and the size of the storage units containing their representations. – John Bollinger Nov 09 '16 at 22:17
  • @dwelch: **Iff** you don't care about where the bits are placed, they can be useful. But in general, if I just need a bunch of flags, I also prefer bit-ops. – too honest for this site Nov 09 '16 at 22:17
  • 1
    Also, @jww, whether `char` is a signed or unsigned type is implementation-dependent; your comment about the possible values of such a field applies only when `char` is signed. – John Bollinger Nov 09 '16 at 22:22
  • @JohnBollinger: "It is implementation-defined whether bitfields can be declared as type char at all." - can you provide a reference to the standard? – too honest for this site Nov 09 '16 at 22:26
  • Thanks @John. I guess that's one of those bugs burned into my mind, so I expect all implementations to have the behavior. When I see the 1-bit bit-fields, I usually convert them to something `OpModes.a != 0`. – jww Nov 09 '16 at 22:30
  • @Olaf: C2011, 6.7.2.1/5: "A bit-field shall have a type that is a qualified or unqualified version of `_Bool`, `signed int`, `unsigned int`, or some other implementation-defined type." That provides for `char`-type bitfields only under the "implementation-defined" alternative. – John Bollinger Nov 09 '16 at 22:33
  • Interesting. They indeed made bitfields even more useless for the area they otherwise would be the best solution: peripheral hardware registers. This one just adds the topping. – too honest for this site Nov 09 '16 at 22:41

1 Answers1

3

There's no formally legal way to do it in one shot.

This is actually a situation in which "manual" implementation of bit-fields (i.e one multi-bit value with access through bitwise operators) is far superior to the language-level declaration of separate 1-bit bit-fields.

Even if you use language-level bit-fields, it is still a good idea to clump closely related flags together onto one larger bit-field instead of separate 1-bit fields (that is flags that have related semantics and thus might have to be processed together). E.g. in your case

#define FLAG_A 0x1
#define FLAG_B 0x2
#define FLAG_C 0x4
#define FLAG_D 0x8

typedef struct
{
    unsigned char abcd : 4;
} _OpModes;

If course, if that abcd is the only field in the struct, there's no real need to use a bit-field at all. Bit-fields exist for packing data, and if there's nothing there to pack, there's no need for bit-fields.

And prefer to use unsigned types for bit-fields unless you have a good reason to use a signed one. In your case, for signed char bit-fields you will end up with "flag" fields with values of 0 and -1. It can be made to work, but still looks weird.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • There is no need for a `struct` anymore. – too honest for this site Nov 09 '16 at 22:03
  • 1
    @Olaf: Yes. But there might be a design-level reason. E.g. "Today all I need is a bunch of flags, but I envision that tomorrow some combinations of these flags might require an additional piece of tag-along data". Something that is called `OpModes` probably does not need to be a struct, but something that's called, say, `OpParams` might be better off as a struct even if today it has only one field. – AnT stands with Russia Nov 09 '16 at 22:05
  • That would leave you at exactly the same position as OP now has. Just define the bitfields as part of an unsigned integer and `typedef` to a fixed-width type of your choice. If 64 bits are insufficient, you have to reconsider the design anyway. – too honest for this site Nov 09 '16 at 22:07
  • @Olaf: I don't understand you last point. I talk about extra tag-along data that might not be even representable as a bunch of bits. If a struct is built into the design early, all I'd have to do is add another field. I don't see how it even relevant to the "position OP now has". – AnT stands with Russia Nov 09 '16 at 22:12
  • Ah, got it. You mean to add other than single bit fields. But that is beyond the question. Hmm, some days (1-2 weeks?) ago we had exactly the same question. I'll try find it. – too honest for this site Nov 09 '16 at 22:15
  • @AnT: Thank you. I got your point. If I Understand Correctly, The flags you created as FLAG_A, FLAG_B are nothing but masks for variable in which each bit depicts a Flag right? – Nagendra Babu Nov 09 '16 at 22:18
  • Found it. Would you support a CV as dup? – too honest for this site Nov 09 '16 at 22:20