I have an enumeration (below) to search. I would do a very simple switch; but I want to have the option of using bitwise OR on the values (e.g. function(option1|option2)). How can I check for this? Surely I don't have to do:
1 2 3 4
switch (options) {
case OPTION1:
case OPTION1|OPTION2|...|OPTIONn:
}
because not only will that give me repetitive strain injury and look stupid; but it would take up like 400 lines of code without even doing anything (except knowing what options it was passed). As the enum can change (I'll probably think of more stuff to add later) it is out of the question to do a switch or if... else ladder.
How can I do this properly?
Here's the enum:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
enum options {
FIRSTOPT, /* This should be left first, see the array below. */
PARENT, /* Execute the program in this process (exits this process) */
CHILD, /* Execute it in a child process */
SIMUL, /* Execute the program in two child processes simultaneously */
TIME, /* Time the execution of the process(s) */
RETURNVAL, /* Get the return value of the process(s) */
LASTOPT /* This should be left last; see the array below */
} opts[LASTOPT - FIRSTOPT]; /* This is to get the amount of options >:)
* because the value of last option is the amount
* of options starting from option 1 (in this case,
* 1).
*/
/* These CAN be |'d, e.g. exec("/bin/program", CHILD|TIME|RETURNVAL);
* However you should use your common sense. PARENT cannot be |'d with anything
* other than SIMUL; which runs three processes (two children and the parent).
*/
I don't understand. If you PARENT|SIMUL, you just get SIMUL. PARENT==1 and SIMUL==3 (I think. I'm not sure if the compiler even assigns any particular sequence by default). Normally, the way flags are set up, each flag is a power of two so that no flag can overwrite another. That pretty much limits how many flags you can have to 32 or 64.
I also don't understand the point of the array opts.
The standard way to check a flag is ((x&flag)==flag). Flags are supposed to be independent from one another, so you don't check them in combination.
Finally, I don't think an enum is the best place to keep flag constants. I'd use macros or constants, depending on my mood.
I don't understand. If you PARENT|SIMUL, you just get SIMUL. PARENT==1 and SIMUL==3
Ah. Major pitfall.
(I think. I'm not sure if the compiler even assigns any particular sequence by default).
It does; I think ANSI says so. The first enumeration is always 0 unless otherwise set; and the ones after it are always the value of the previous enumeration + 1. So if you wanted negatives you'd have to either reverse the list, remember to do Enumeration = -Enumeration or just assign them yourself.
I also don't understand the point of the array opts.
The purpose of the array is to have the same amount of elements as there are options. For example, FIRSTOPT is 0 and LASTOPT is 7. So LASTOPT - FIRSTOPT is 7. So the size in bytes of the array divided by the size in bytes of it's first element (the type itself) is the amount of elements in the array, which is LASTOPT - FIRSTOPT - 1. Therefore with a simple macro: #define SZ_ARRAY(array) ((sizeof(array)) / sizeof(*array))
I can get the amount of options so I don't have to hard-code it (means I only have to change one thing; so I'm less likely to forget how many enumerations there are because I can just do an SZ_ARRAY(opts) + 1 (for the 0 element).
The standard way to check a flag is ((x&flag)==flag). Flags are supposed to be independent from one another, so you don't check them in combination.
Finally, I don't think an enum is the best place to keep flag constants. I'd use macros or constants, depending on my mood.
Ok. I'll do it like that.
But then; how do they implement options like you get in SDL functions; e.g.
screen = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)? I always assumed that was an enumerated list of possibilities and they got the value of the |... How does that work? That's what I'm trying to do.
I'm still not really understanding this... How do I check for multiple flags? I check if [number] & flag == flag... So I should check x & userFlag against myFlag?
Like this:
What happened to working with enum? Helios is correct about the definition of values but there is no reason that macros are needed is there? You could certainly accomplish the same thing with the enum and and inline functions.
1 2 3 4 5 6 7
enum eStates
{
STATEA= 1,
STATEB = 2,
STATEC = 4,
STATED = 8 // and so forth
};
Agreed. The problem with the example is that it is mixing two types of numbers: indices and bit-values.
The one that gives you an index (into an array and the like) is a normal, whole number: 0, 1, 2, 3, 4, etc.
The one that is a bit value is not necessarily correlated -- though for a straightly disjoint set it could correlate as bit-indices: 1, 2, 4, 8, 16, etc.
The point of bit-values is essentially that it is a packed array of booleans (represented by individual bits). The STL vector class actually has a specialization that does this (vector<bool> -- a design mistake, BTW).
If you really need additional information than a simple boolean bit, then you need to keep track of things separately. What exactly are you trying to accomplish? Perhaps we can suggest a better way... Does it need to be C-compatible, or can C++ stuff be used?