bph
bph

Reputation: 11268

Comparison of several integer values for equality

If I have two integer values I can test for equality simply:

if (a == b)

if I have three integer values then I could do something like:

if ((a == b) && (a == c) && (b == c))

I've got a situation where I've got 6 values to test for equality, this approach is going to get verbose

Is their a better, and more C idiomatic (c-onic?) means to achieve this?

actually, just having written this I can see that:

if ((a == b) && (b == c) && (c == d)... )

is logically ok, i.e. you don't need all the combinations as a == b and b == c implies a == c

But in terms of clarity of expression how close can I get to:

if (a == b == c) ?

Upvotes: 6

Views: 194

Answers (4)

John Zwinck
John Zwinck

Reputation: 249552

I can show you how to do it in a variadic macro, so we can write this:

if(EQI(a, b, c, d, e, f))

Here's the code:

#include <stdarg.h>
#include <stddef.h>

#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__}) / sizeof(int))
#define EQI(...) ( \
    alleqi(NUMARGS(__VA_ARGS__), __VA_ARGS__))

/* takes count number of int arguments */
int alleqi(size_t count, ...)
{
    va_list va;
    va_start(va, count);

    int v0 = va_arg(va, int);

    for (; count > 1; count--) {
        if (v0 != va_arg(va, int)) {
            break;
        }
    }

    va_end(va);
    return count == 1;
}

Please be advised the above only works for int arguments (and probably other types whose size is the same as int, though I am bracing for someone to accuse me of promoting undefined behavior if I advertise that!).

Thanks to this prior post for figuring out how to count arguments in a variadic macro: https://stackoverflow.com/a/2124433/4323

Upvotes: 7

user2404501
user2404501

Reputation:

You're not going to get very close to a == b == c.

To cause experienced C programmers the least surprise, I think this is best is

if(a == b && b == c && c == d && d == e && e == f)

i.e. basically like what you have already, with less parentheses. I'm not always opposed to adding parentheses that make no difference to the compiler to help humans who don't know all the precedence rules, but I think comparisons separated by && (with no || mixed in) are a simple enough case that the parentheses are more clutter than they're worth.

If the variable names are long, putting it all on one line isn't going to be pretty, so maybe

if(a == b &&
   b == c &&
   c == d &&
   d == e &&
   e == f)

or this might be better since the duplication of the the a in every line will be immediately noticeable:

if(a == b &&
   a == c &&
   a == d &&
   a == e &&
   a == f)

If you really want it to be compact, the p99 preprocessor library offers this:

#include "p99_for.h"

if(P99_ARE_EQ(a,b,c,d,e,f))

which looks like John Zwinck's answer but doesn't require a helper function.

Upvotes: 7

Paul Ogilvie
Paul Ogilvie

Reputation: 25286

Approaches using arrays require you to change your data structure into an array.

Approaches using a variadic macro requires an additional function and function call (overhead).

Except for these two approaches, the only other way I see is to write them out. I feel the best way, or the more clear way, is to take the first variable and compare it to all other variables. By implication then either all variabes are equal, or at least two variables are unequal:

if ((a == b) && (a == c) && (a == d)
&&  (a == e) && (a == f) && (a == g) ...)

Upvotes: 2

Rishikesh Raje
Rishikesh Raje

Reputation: 8614

If you want to check six values, one approach would be to store them in an array

int a[6];

equals = 1;
for (int i=0; i<5; i++)
{
    if (a[i] != a[i+1])
    {
       equals = 0;
       break;
    }
}

Upvotes: 6

Related Questions