0

I would like to sum over a number of bool variables to find out how many of them are TRUE. Since there is no real bool type in C (only int), I cannot be entirely sure that TRUE means exactly 1. It could theoretically be any integer greater than zero. What is a computationally efficient and readable way to ensure this?

P.S. I am aware of this similar question. However, my case is slightly different, as the bool values don't come from an internal truth check, but from an external source (CAN signal).

Dave
  • 171
  • 2
  • 13
  • `if (TRUE == 1) ....` But this is quite useless exercise as the standard guarantees that `true` defined in `stdbool.h` expands to `1` – Eugene Sh. Jan 31 '22 at 16:22
  • 2
    C does have a Boolean type, since C 1999. It is called `_Bool`, and `` adds `bool` as an alias. – Eric Postpischil Jan 31 '22 at 16:24
  • 3
    I suspect your actual question is you want to count the number of non-zero values in a number of items. Ideally their values would be 0 or 1, but you do not trust where they came from and now want to count the number of non-zero values rather than simply adding them all. Suppose they have integer type, you can do this with `sum += (_Bool) x;`, `sum += !!x;`, or `if (x) ++sum;`. – Eric Postpischil Jan 31 '22 at 16:26
  • If, if true is “any integer greater than zero”, and you have to deal with negative values that mean false, then you can use `sum += 0 < x;` or `if (0 < x) ++sum;`. You should edit to clarify the problem. – Eric Postpischil Jan 31 '22 at 16:28
  • 1
    @EricPostpischil Thanks for re-formulating my question more precisely. This is exactly what I wanted. I like `sum += !!x;` best, as it is works without external libraries and avoids an additional `if` check. – Dave Jan 31 '22 at 16:54

1 Answers1

2

Never use a _Bool (or bool defined by #include <stdbool.h>) if it is possible for the object to contain a value other than 0 or 1. The compiler is at liberty to assume the object will contain a value of 0 or 1 and produce unexpected results if it contains a different value. In particular, GCC tends to produce unexpected results from the following program:

foo.c

#include <stdio.h>
#include <string.h>

int main(void)
{
    _Bool b;
    memset(&b, 0xff, sizeof b);
    printf("int = %d\n", (int)b);
    printf("int_bool = %d\n", (int)(_Bool)b);
    printf("int_bool_int = %d\n", (int)(_Bool)(int)b);
    printf("int_not_not = %d\n", (int)!!b);
    printf("not_not_int = %d\n", !!(int)b);
    return 0;
}

On Debian GNU/Linux 11 x86_64:

$ gcc --version
gcc (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc -O2 foo.c -o foo
$ ./foo
int = 255
int_bool = 255
int_bool_int = 255
int_not_not = 255
not_not_int = 255

One might have expected most of those printed values to be 1 rather than 255.

Ian Abbott
  • 15,083
  • 19
  • 33
  • 1
    This is a weird one. It happens even with -O0, and according to godbolt it was gcc 9.4 that first exhibited this. – dbush Jan 31 '22 at 18:05