2

I'm migrating an application I was developing in CodeWarrior v5.2 to Keil uVision v5.25, which uses the ARM C compiler v5.06.

Throughout my code I've used bool to represent boolean values, which is defined in a types.h file in my project as:

typedef enum _bool 
{ 
  false = 0, 
  true = 1 
} bool;

When I try to compile my code, the compiler generates warnings about lines where I implicitly assign the outcome of comparisons to variables with this type:

src\c\drivers\motor.c(168): warning:  #188-D: enumerated type mixed with another type
    const bool motorStopped = timeSinceLastEvent > maxPulseWidth;
src\c\drivers\motor.c(169): warning:  #188-D: enumerated type mixed with another type
    const bool motorStalled = motorStopped && isMotorDriven();

I understand why these warnings are being generated. I'm aware that I can suppress these warnings by explicitly casting to bool, like:

const bool motorStopped = (bool)(timeSinceLastEvent > maxPulseWidth);

However, doing this for every boolean condition is pretty ugly. I was wondering if there's a way I can configure Keil uVision / the ARM compiler (or modify my code) to not generate warnings about bool, without outright disabling warnings about mixing enumerated types with other types.

These are the options I have available to configure the compiler:

Tagc
  • 8,736
  • 7
  • 61
  • 114
  • Why not typedef bool as int? – Ctx Jul 18 '18 at 10:47
  • @Ctx Why not use the standard type and the macros? You are not supposed to define names which are part of the standard library at all. Defining your own `bool` can break standard compliant code. – too honest for this site Jul 18 '18 at 10:54
  • 1
    @Ctx not a bad idea, this "types.h" file also has `typedef unsigned char boolean;` along with `TRUE` and `FALSE`. Switching all my `bool`s to `boolean`s seems the best idea. – Tagc Jul 18 '18 at 10:55
  • And don't use custom headers with the same name as standard headers either. Your compiler **has to** provide a minimal set at least. If there is no `types.h`, there might be a reason why. If there is, it should work with the compiler and comply to the standard. – too honest for this site Jul 18 '18 at 10:57
  • @Olaf I didn't, it's a third-party file that came with an SDK kit. The `bool` type defined in this file is also used in a lot of the SDKs and if I used the type defined in `stdbool.h`, it would shadow it. Otherwise, I would use stdbool.h. – Tagc Jul 18 '18 at 10:57
  • 1
    Can I ask why this question was downvoted? – Tagc Jul 18 '18 at 10:57
  • So ask the vendor of that "thing" to make it C compliant! No reasonable company should accept non-standard C code. That typedef can easily break other parts of your (or maybe some other external library which **is** compliant). – too honest for this site Jul 18 '18 at 10:59
  • As reference, this is the third-party `types.h` file that gets included in the project. https://hastebin.com/rocosaraji.c – Tagc Jul 18 '18 at 11:05
  • 1) we won't click external links. 2) Did you make sure you don't violate the copyright of the author of that file? – too honest for this site Jul 18 '18 at 11:09
  • 1
    1) If you don't want to, that's fine - others might want to see the file 2) The copyright is at the top of that file and says redistribution is fine so long as the copyright is included and not used for endorsement – Tagc Jul 18 '18 at 11:10
  • @Olaf Actually, I think I know why they've done it that way - `stdbool.h` isn't available in C89, and so they may have defined it themselves so that the `bool` type is available regardless of what C standard is being used. I defined a similar enum when I was working with another micro with CodeWarrior 5.2 and was forced to use C89. – Tagc Jul 18 '18 at 11:17
  • 1
    C89 is not standard C. And this is compiled as C99 (also not standard, but maybe the best you get with proprietary commercial compilers). – too honest for this site Jul 18 '18 at 12:10

2 Answers2

1

It felt dirty, but I resolved this by modifying the types.h file that came with the SDK kit by making it include stdbool.h instead of defining its own bool type. Recompiling my project produced no warnings/errors in either the third-party code that used bool or my own code.

For good measure I tried modifying it in a way that should still let it work if it were compiled in a C89 project:

#if __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#endif

// ...

#if __STDC_VERSION__ < 199901L
typedef enum _bool 
{ 
  false = 0, 
  true = 1 
} bool;
#endif
Tagc
  • 8,736
  • 7
  • 61
  • 114
-2

First of all, these kind of definitions are not logically correct in C.

C defines false as zero and true as not zero, which of course includes 1 but not only that. It can be dangerous in many situations:

The expression if(GetValue() == true) only evaluates as true if the return value of the function is 1. It is extremely dangerous, and may be the source of many difficult-to-discover errors.

bool can have any value as int is the type behind it.

Casting does not change anything:

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

typedef enum _bool 
{ 
  false = 0, 
  true = 1 
} bool;

int main(void) {

    bool x;

    x = 50;
    printf("%d\n", x);

    x = (bool)50;
    printf("%d\n", x);
}

https://ideone.com/nNHPLg

You will explicitly convert the int values to zeroes or ones. For example:

bool x = !!something;

bool x = something ? true : false;

Tagc
  • 8,736
  • 7
  • 61
  • 114
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    According to the standard `true` is a macro which expands to the **integer constant** `1` which has type `int`. `false` to `0`. So, `true` **is** in fact `1`, not "not `0`". You confuse the macros and `_Bool` standard type with how the result of a condition are interpreted by compound statements, resp. the conditional operator. And the code you show makes clear what`s wrong with the `typedef. `(bool)50` evaluates to `1` according to the standard. It can **only represent the value `0` and `1`. – too honest for this site Jul 18 '18 at 11:03
  • Finally: The underlying type for an `enum` is not not guaranteed to be `int`. The _enum-constants_ have `int` type, but an object of a `enum` type need not. The implementation can choose a smaller type. That's one major problem with `enum`s in C. As a result such an object might not bne able to hold all values `int` can. – too honest for this site Jul 18 '18 at 11:07
  • 1
    @Olaf - yes but the smallest int type is char which can accommodate more than 0 and one only. The underlying type is one of the integer types. Standard says that any nonzero value is considered as true, only the the results of the logical operations are guaranteed to be `0` or `1`. – 0___________ Jul 18 '18 at 11:11
  • 1
    @Olaf IMO defining type bool makes sense only in the languages which do not allow implicit type conversions (like C++ for example). Otherwise comparition to the `true` may give the incorrect results - like in my answer. – 0___________ Jul 18 '18 at 11:15
  • 1
    @Olaf - and lastly I do answer the particular question where it is defined as it is defined (it is not the `bool` type from the stdint.h) – 0___________ Jul 18 '18 at 11:23
  • 1
    The code is complies as C99, which makes my objections valid. And `char` is an **integer** txype, not an `int` type. In programming and expecially for beginner we should be precise. You wrote "`bool` can have any value as `int` is the type behind it." which I corrected as it's plain wrong stated this general. And defining `bool` does not make sense at all, as C99+ **does have** a boolean type and `bool` as specified by the standard has different implicatgions than an `enum` or any other standard type (that's why it was added). Try `_Bool b = 50;`! – too honest for this site Jul 18 '18 at 12:03
  • @Olaf it is nitpicking. The build in bool types generate completely different code than this enum one. And those are not considered in this question. Focus on the question not on the general off topic deliberations. The question is about **enum** type typedefed by the OP. Defining a bool type this way in C is a very bad idea – 0___________ Jul 18 '18 at 12:26
  • Apparently OP **did** focus on the question and my comments. See his answer, he **did** use the standard way. I'd possibly kicked the vendor, but we don't know the details. After all, his way only might break the library (less likely, unless it's completely messed up), not the application or compliant code. Funny: Your last sentence is almost exactly what I wrote initially … – too honest for this site Jul 18 '18 at 13:11
  • @Olaf my answer is about it. Why he should not doing it this or similar way. – 0___________ Jul 18 '18 at 13:30