Hi all,
is there a boolean type in xc? I can't find one and the compiler complains if I try to use stdbool.h.
If there isn't, why?
Thanks!
Wot no bool?
-
- Respected Member
- Posts: 367
- Joined: Wed May 31, 2017 6:55 pm
-
- XCore Legend
- Posts: 1913
- Joined: Thu Jun 10, 2010 11:43 am
-
- XCore Addict
- Posts: 169
- Joined: Fri Oct 23, 2015 10:23 am
Hi CousinItt,
There is no bool type in the XC language (although it is something that should be added and has been pending too long).
A true bool type is a one bit type (not 8 or 32) and is implicitly coerced to and from other integral types - thus there is a fair bit of work to do when adding it!
Until then, you must use one of the other integral types (e.g. int) and work with the coercion rules as with pre C99 e.g. '#define FALSE 0', '#define TRUE !FALSE'
robert
p.s. Using an integral with more than one bit does have the advantage that you can have alternative truths....
There is no bool type in the XC language (although it is something that should be added and has been pending too long).
A true bool type is a one bit type (not 8 or 32) and is implicitly coerced to and from other integral types - thus there is a fair bit of work to do when adding it!
Until then, you must use one of the other integral types (e.g. int) and work with the coercion rules as with pre C99 e.g. '#define FALSE 0', '#define TRUE !FALSE'
robert
p.s. Using an integral with more than one bit does have the advantage that you can have alternative truths....
-
- Respected Member
- Posts: 367
- Joined: Wed May 31, 2017 6:55 pm
@mon2 ?
@robertxmos Thanks for the fulsome reply. That's exactly the type I'm looking for. I'm surprised it will take so much work, but I'm glad it's on the roadmap. As you suggest, I'll make do in the meantime.
p.s. groan
@robertxmos Thanks for the fulsome reply. That's exactly the type I'm looking for. I'm surprised it will take so much work, but I'm glad it's on the roadmap. As you suggest, I'll make do in the meantime.
p.s. groan
-
- Respected Member
- Posts: 507
- Joined: Wed Apr 25, 2012 8:52 pm
If I add #include <stdbool.h> and add -std=c99 or -std=gnu99 to the XCC flags, to me it complains about:
So it seems like the compiler doesn't have _Bool as an intrinsic type, not even for C99?
In <stdbool.h> one could have
satisfied and I guess it will work, but that's not the setup, is it? In case, how are they set?
By the way, Robert, will there be a big difference between these three. I guess all will be autmatically coerced to int and then work. 1 is in the !FALSE set and should suffice(?):
I have used A and B over the years, but C was new to me. Not even <stdbool.h> uses C. And D is really new to me! I don't even know how to interpret D!
I have a short chapter about bool (where <stdbool.h> is shown) and XC here: XC code examples (disclaimer: no money, no ads, no gifts. Only expenses and fun).
Code: Select all
error: use of undeclared identifer `_Bool'
In <stdbool.h> one could have
Code: Select all
defined(__GNUC__) && !defined(__STRICT_ANSI__)
By the way, Robert, will there be a big difference between these three. I guess all will be autmatically coerced to int and then work. 1 is in the !FALSE set and should suffice(?):
Code: Select all
// A:
typedef enum {false,true} bool; // 0,1
// B:
#define FALSE 0
#define TRUE 1
// C:
#define FALSE 0
#define TRUE !FALSE
// D: from the above #ifdef in <stdbool.h>. I guess this assumes that "bool" is defined?
#define _Bool bool
#define bool bool
#define false false
#define true true
I have a short chapter about bool (where <stdbool.h> is shown) and XC here: XC code examples (disclaimer: no money, no ads, no gifts. Only expenses and fun).
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- XCore Addict
- Posts: 169
- Joined: Fri Oct 23, 2015 10:23 am
_Bool is available in 'C99' but not in 'xC', thus the header file <stdbool.h> won't work with 'xC'.
If you don't have a true 1bit type (xC and pre C99) and try to represent it using say a 32bit type, be careful when comparing against a literal representation e.g. 'TRUE'.
Whilst there may be only one 'FALSE' literal there may be many truths.... and my truth may be different from yours :-)
e.g.
It is annoying that the compiler internally uses 1bit types (logical results & implicit conversion for conditional statements)
and yet the user can't explicitly use them in code - sorry.
robert
If you don't have a true 1bit type (xC and pre C99) and try to represent it using say a 32bit type, be careful when comparing against a literal representation e.g. 'TRUE'.
Whilst there may be only one 'FALSE' literal there may be many truths.... and my truth may be different from yours :-)
e.g.
Code: Select all
BOOL hasItem(Item i) {
int i = findItemIndex(i); // returns -1 if it is not there.
return i+1; // if not there return 0, otherwise a value that can be converted to boolean true.
}
if (hasItem(i) == TRUE) { /* 32bit comparison is only true if index was '0' */ }
if (hasItem(i)) { /* convert to 1bit, hence all index values are true */ }
and yet the user can't explicitly use them in code - sorry.
robert
-
- Respected Member
- Posts: 507
- Joined: Wed Apr 25, 2012 8:52 pm
Important point!
However, I would have returned two values, {unsigned, bool} for {index, found} and in that case bool/found would always have been uniquely defined and both comparisons would be correct.
I think you state that A, B, C and D would all be wrong with the example you show?
Of course, with bool defined in the language then return i+1 would not be compilable. It's not bool. And if the type conversion were algorithmically wrong, that's the programmer's problem. In my opinion it's coding horror to return -1 on error anyhow, even if it's a coding standard all around.
However, I would have returned two values, {unsigned, bool} for {index, found} and in that case bool/found would always have been uniquely defined and both comparisons would be correct.
I think you state that A, B, C and D would all be wrong with the example you show?
Of course, with bool defined in the language then return i+1 would not be compilable. It's not bool. And if the type conversion were algorithmically wrong, that's the programmer's problem. In my opinion it's coding horror to return -1 on error anyhow, even if it's a coding standard all around.
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- Respected Member
- Posts: 507
- Joined: Wed Apr 25, 2012 8:52 pm
Triggered by Rober's important point earlier I made some code where that problem will not appear, and tested it. Along the line of my last comment.
However, I discovered something else, see USE_WRONG_RETURN_LIST. See in and below the code:
Defining USE_WRONG_RETURN_LIST shows that the compiler will use any integer type for any definition I may have of bool. So, in this case I won’t get any help from the compiler. I may compile wrong code. I guess that’s not much worse than having any list of (..,signed,signed,..) parameter in any function, where (..,degC,degF,..) or (..,degF,degC,..) may be done wrongly. However, there is a small difference. With USE_WRONG_RETURN_LIST the compiler could have taken it if bool were understood by the compiler.
So, not even a typedef of the bool makes it a unique type to the compiler. It's still an integer-type type.
So, let's get real bool!-)
However, I discovered something else, see USE_WRONG_RETURN_LIST. See in and below the code:
Code: Select all
#include <stdio.h>
#include <iso646.h> // For "not" etc
#define USE_BOOL_TYPEDEF // No difference since no type conversions done
#ifdef USE_BOOL_TYPEDEF
typedef enum {false,true} bool; // 0,1
#else
#define bool unsigned // long, int, unsigned, char, bool ok
#define false 0
#define true 1 // Or "not false"
#endif
typedef unsigned index_t; // long, int, unsigned, char, bool compile ok..
// #define USE_WRONG_RETURN_LIST // ..with this defined
{index_t, bool} isItemIn (
const char search_for,
const char text[],
static const unsigned len) {
index_t index = 0;
bool found = false;
bool searching = true;
while (searching) {
if (text[index] == search_for) {
found = true;
searching = false;
} else {
index++;
if (index == len) {
searching = false;
} else {} // No code, maybe next round
}
}
return {index, found};
}
int main() {
const char text[] = {'A','B','C','D','E','F','G','H','I','J'};
index_t index;
bool found;
{index, found} = isItemIn ('C', text, sizeof(text));
if (found) {
printf("C found in %u\n", index);
} else {
printf("C not found\n");
}
#ifdef USE_WRONG_RETURN_LIST
{found, index} = isItemIn ('X', text, sizeof(text));
#else
{index, found} = isItemIn ('X', text, sizeof(text));
#endif
if (not found) {
printf("X not found\n");
} else {
printf("X found in %u\n", index);
}
// LOG with
// USE_WRONG_RETURN_LIST not defined
// USE_BOOL_TYPEDEF or not no difference
// C found in 2
// X not found
return 0;
}
So, not even a typedef of the bool makes it a unique type to the compiler. It's still an integer-type type.
So, let's get real bool!-)
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- XCore Addict
- Posts: 169
- Joined: Fri Oct 23, 2015 10:23 am
> So, not even a typedef of the bool makes it a unique type to the compiler. It's still an integer-type type.
Correct, typedef should be viewed as a handy alias.
One could argue that instead of tightening a type system it does the opposite!
If you want unique types you need to reach for struct/union (class if using c++ & interface if using xC)
Even 'enum' is weak (unlike the 'enum class' in c++11)
Correct, typedef should be viewed as a handy alias.
One could argue that instead of tightening a type system it does the opposite!
If you want unique types you need to reach for struct/union (class if using c++ & interface if using xC)
Even 'enum' is weak (unlike the 'enum class' in c++11)
-
- Respected Member
- Posts: 507
- Joined: Wed Apr 25, 2012 8:52 pm
You are triggering me again!
Since interface is not for the below code, I collected the {index,found} into a struct. I guess it's less error prone since it's easier to asign x.index=index than x.index=found. Even if I don't do that, I do use it explicitly like isItemIn_return.index++. Doing it wrongly with isItemIn_return.found++ is easy to spot since I would think to increment a verb would ring a bell.
This uses the same amount of code and data as the above code. Maybe this indicates that the compiler also builds a struct for the parameter list? I kind of like it:
Since interface is not for the below code, I collected the {index,found} into a struct. I guess it's less error prone since it's easier to asign x.index=index than x.index=found. Even if I don't do that, I do use it explicitly like isItemIn_return.index++. Doing it wrongly with isItemIn_return.found++ is easy to spot since I would think to increment a verb would ring a bell.
This uses the same amount of code and data as the above code. Maybe this indicates that the compiler also builds a struct for the parameter list? I kind of like it:
Code: Select all
#include <stdio.h>
#include <iso646.h> // For "not" etc
typedef enum {false,true} bool; // 0,1
typedef unsigned index_t; // long, int, unsigned, char, bool compile ok..
typedef struct { // easier to get right than the anonymous return parameter list
index_t index;
bool found;
} isItemIn_return_t;
isItemIn_return_t isItemIn (
const char search_for,
const char text[],
static const unsigned len) {
isItemIn_return_t isItemIn_return = {0, false}; // Not type safe as {true, 0} will compile
bool searching = true;
while (searching) {
if (text[isItemIn_return.index] == search_for) {
isItemIn_return.found = true;
searching = false;
} else {
isItemIn_return.index++;
if (isItemIn_return.index == len) {
searching = false;
} else {} // No code, maybe next round
}
}
return isItemIn_return;
}
int main() {
const char text[] = {'A','B','C','D','E','F','G','H','I','J'};
isItemIn_return_t isItemIn_retval;
isItemIn_retval = isItemIn ('C', text, sizeof(text));
if (isItemIn_retval.found) {
printf("C found in %u\n", isItemIn_retval.index);
} else {
printf("C not found\n");
}
isItemIn_retval = isItemIn ('X', text, sizeof(text));
if (not isItemIn_retval.found) {
printf("X not found\n");
} else {
printf("X found in %u\n", isItemIn_retval.index);
}
// LOG with
// USE_BOOL_TYPEDEF or not no difference
// C found in 2
// X not found
return 0;
}
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/