In a C project (OpenVPN is the project in question, commit 4029971240b6274b9b30e76ff74c7f689d7d9750) we had a emulation of bool
typedef int bool;
#define false 0
#define true 1
and now switch to C99 bool
#include <stdbool.h>
But in the project there is somewhere a bad usage of the bool. I know that the std bool behaves different. E.g.
bool t;
t=2;
if ( t == true)
printf("True!\n");
else
printf("False!\n");
Will return True! with stdbool.h
and False! with the #define
emulation.
My question Is there a way to find these code parts that behave different with stdbool and the emulated bool? Perhaps some compiler flag I overlooked or a good llvm or gcc intermediate format that can be diffed?
It is nothing as simple as in the example above but must be something that not as easy to see. Definitively not a == true.
UPDATE: We found the issue (mbuf_set has an int member len). It kind of stupid but the question still remains how to catch these. I am surprised the integer overflow checks don't catch things like this:
static inline bool
mbuf_len (const struct mbuf_set *ms)
{
return ms->len;
}
The kind of usage you're describing is correct, well defined behaviour. So the compiler will not produce any warnings. One possible way around this is to change the typedef
:
typedef enum {false, true} bool;
This will still allow the code to compile without error (as it's well defined), but you may be able to force warnings from a compiler or analyser. For example, clang
will pick this kind of thing up with -Weverything
:
$ clang -o a a.c -Weverything
a.c:7:11: warning: integer constant not in range of enumerated type 'bool'
[-Wassign-enum]
bool n = 2;
Of course this will not do any runtime checking. It will still allow the typedef
bool variable to be changed to something other than 0 or 1 (e.g. via a function call or in an expression). The only way to detect those instances is to use a debugger.
The macros for true and false in stdbool.h
are designed really only for the _Bool
type. This is because this type can only hold the values 0 and 1; any value you assign that isn't 0 is stored as 1. So for a boolean type only, the true and false macros are guaranteed to work.
Without the _Bool
type, there's no way to have the language itself do this for you directly, because there's no comparable type, and you'd effectively be asking it to allow that 2 == 1
returns true.
There are a few ways to implement the same behaviour, e.g. using a macro such as BOOL(n)
in every instance of using the variable n
, to ensure its value is 0 or 1 only. This way, you'd get the same result whether using _Bool
or an int
for n
. For example:
#define BOOL(n) ((n) != 0 ? 1 : 0 )
bool b = rand() % 100;
if (BOOL(b) == true) ...
This would work whether using stdbool
or a typedef
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With