1

I tried googling and failed.

Using C, I have an IF statement. I want to test a variable against two non-consecutive values.

Is it possible to do

if (state == 1 || 3)

Meaning if state is 1 or if state is 3.

Or does it have to be

if (state == 1 || state == 3)

I'm thinking the first actually means if state is 1, or 3, which means the test will always be true (if true or true).

Is there a way to write this without having to rewrite the variable name multiple times?

No, I don't want to use a case / switch statement. I'm trying to type less.

16
  • Have you had a look at the formal grammar defined in the C-standard? Specifically C11 draft standard n1570, 6.5 Expressions? Commented Mar 11, 2016 at 22:24
  • 1
    To save typing you could perhaps use a macro, #define TEST2(var, a, b) ( (var) == (a) || (var) == (b) ). (bear in mind that this evaluates var twice still). You could write an inline function to avoid the double evaluation. If you have many cases then use a switch. Commented Mar 11, 2016 at 22:26
  • @M.M The best part of that macro is that you can even do TEST2(a++, 1, 3) and the behavior is well defined. That's a wonderful thing, and kind of rare for macros. Commented Mar 11, 2016 at 22:28
  • 1
    @cde Aside from 1 or 3, what values might state have? 0, -1, 1000000, 1.23? Commented Mar 11, 2016 at 22:58
  • 2
    It probably took you more time to ask the question (by typing) than it will save you all year in typing code! Commented Mar 11, 2016 at 23:01

3 Answers 3

2

you have to use the long variant

if (state == 1 || 3)

evaluates always to true because it is interpreted as

if ((state == 1) || (3))

EDIT:

Because for C++ was asked in the comments an M.M mentioned operator overloading, a C++ solution

#include <cstdlib>
struct State {
    struct Proxy {
        int v;
        bool res;
        Proxy(int v, bool res) : v(v), res(res) {}

        Proxy operator || (int a) const {
            return Proxy(v, res || (a == v));
        }

        operator bool() const { return res; }
    };
    int v;
    State(int v) : v(v) {}

    Proxy operator == (int a) {
        return Proxy(v, a == v);
    }
};


int main(int argc, char *argv[])
{
    State   state(atoi(argv[1]));

    if (state == 1 || 3 || 5)
        return 1;
    else
        return 0;
}
Sign up to request clarification or add additional context in comments.

8 Comments

That's what I was thinking. So there's no short form option at all?
nothing, which would be shorter than (state == 1) || (state == 3). Depending on your use case you can define macros to avoid writing redundant code. Our -- when state is small-- you can define a table to speedup check when many cases must be checked.
Does c++ address this?
no; neither C nor C++ have a native is in operator.
obviously you could write an if ( is_in(state, 1, 3) ) in both languages
|
1

@cde, 'C' programming doesn't have a construct to use the expression like in the first form, so you have to use the second form, as many have already mentioned above.

You might try the following approach, if the values are known ahead of comparison, either by including them at the time of declaration or populate with the values at a later time (which might of fixed or variable set, in which case the array has to be allocated dynamically and size must have already been available by then).

Note: inline, static, const aren't really necessary for the solution to work. Also, it has the advantage that the function returns as soon as the condition evaluates to true skips the rest of the comparisons, unless the state doesn't match with any of the given states.

#include <iostream>

using namespace std;


inline bool isInKnownStates(int state, const int ds[], const int sz)
{
    int i = 0;

    for (; (i < sz) && (state != ds[i]); i++);

    return (i < sz);
}

int main(int argc, const char * argv[]) {

    static const int discrete_states[] = {1, 3};
    static const int sz = sizeof(discrete_states)/sizeof(discrete_states[0]);
    int state0 = 0;
    int state1 = 1;
    int state3 = 3;

    cout << state0 << " " << (isInKnownStates(state0, discrete_states, sz) ? "True" : "False") << endl << flush;
    cout << state1 << " " << (isInKnownStates(state1, discrete_states, sz) ? "True" : "False") << endl << flush;
    cout << state3 << " " << (isInKnownStates(state3, discrete_states, sz) ? "True" : "False") << endl << flush;

    return 0;
}

1 Comment

Sure. It might not be as simple as multiple individual expressions as in second firm, and not having to write it multiple times make it easier to use. Also lends it to the form that @sun-qingyao mentioned below. For example, cout << state0x1000 << " " << (isInKnownStates(state0x1000, (int[]){1, 3, 256, 0x1000}, 4) ? "True" : "False") << endl << flush; works correctly. The memchr only for integer values that can be specified using 'char' type as the function expects and treats the values as chars rather than int.
0

Is there a way to write this without having to rewrite the variable name multiple times?

Well, yes. #include <string.h> and you can use

if(memchr(&(char []){1, 3}, state, 2))

0r

if(memchr(&(char []){1, 3, 5, 7, 9}, state, 5))

Note that state mustn't contain values beyond the scope of char(signedness can be specified as need), or information might be lost. You cannot use an array of type T when sizeof (T) != 1. The reduce of readability will also be taken into consideration.

1 Comment

This will also evaluate as true for state == 0. I'd say it's a bad idea to call memchr() on an int-array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.