Return True or 1? - c

As I know, Boolean is basically a char datatype, one byte, 0x00 or 0x01. Also, as I know, Integer is multiple bytes.
bool foo () {
return true; // I guess is 0x01 one byte
return 1; // I guess is 0x00000001 four bytes (depend on the platform)
}
Why do both returns work?

Here is what the C 2017 standard says about bool (aka _Bool) so "basically a char" is not correct:
An object declared as type _Bool is large enough to store the values 0 and 1. (6.2.5)
return 1 works due to automatic type conversion:
When any scalar value is converted to _Bool , the result is 0 if the value compares equal to 0; otherwise, the result is 1 (6.3.1.2)
There is no "best practice" as far as I know. I did not see it covered in MISRA C for instance. It may be covered in coding guidelines for your project(s) though. I use 0 and 1 as I favor compact code.

As others have explained, the size of a bool is not specified by the standard, so a compiler implementation is free to use any size as long as it can hold the values 0 and 1.
My clear recommendation is to use a bool type if the information is true/false by nature. Using an integer as boolean can lead to subtle errors. Consider the following (inspired by a real-life bug):
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
uint8_t isThisTrueInt(void)
{
int x = 256;
return x;
}
bool isThisTrueBool(void)
{
int x = 256;
return x;
}
int main(void)
{
printf("%s\n", (isThisTrueInt())?"true":"false");
printf("%s\n", (isThisTrueBool())?"true":"false");
return 0;
}
The result is:
false
true
The point being that converting 256 to an 8-bit integer truncates to 0, i.e. "false" while conversion to bool will give "true" for any non-zero integer.

As I know, Boolean is basically a char datatype, one byte, 0x00 or 0x01
That is not the case, the size of bool type is implementation-defined and is not specified in the C standard, it is usually defined in stdbool.h as of C99 and is normally something like:
#define bool _Bool
#define false 0
#define true 1
Before that it wasn't even a mandated type. You can say that in some implementations it's equivalent to a single byte, but not always, the specification only requires that bool is large enough to hold the values 0 or 1 and this ranges from 1 bit to the largest type possible, natively long long.
What's the best practice to follow?
This is an opinion based question, still, thinking about it, I would advise to use true/false because it's a pattern used in pretty much all the languages and it'll surely be easier to understand, I must admit I'm not the best follower of such practice as I often use 0/1.
This is all overrided by your project/company coding practices or guidelines, if that's the case.
Why do both returns work?
In C, any non-zero value is considered to be true (this includes negative values) in a boolean context, whereas 0 is considered to be false as can be seen in N1570 Committee Draft of April 12, 2011 ISO/IEC 9899:201x:
ยง6.3.1.2 Boolean type
1 When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.59)
Footnotes
59) NaNs do not compare equal to 0 and thus convert to 1.

Related

Compare two bools with different int value

#include <stdbool.h>
#include <stdio.h>
int main ()
{
bool a, b;
a = 1;
b = 4;
if (a == b)
printf ("They are equal\n");
else
printf ("They are different\n");
}
This code prints They are equal
How can this happen? Are the variables a and b being filled with the value 0x1 in the assignment regardless of what I assign to them? Or maybe is it the == that has been hacked to handle bools?
Is this behaviour portable accross C Standard Library implementations and compilers?
What was the correct way of logically comparing two bool/int before the introduction of stdbool.h ?
How can this happen?
Both variables are 1, so they are equal.
Are the variables a and b being filled with the value 0x1 in the assignment regardless of what I assign to them?
Well, not regardless. Any non-zero value is converted to 1 and assigned to bool. A zero value will fill them with... 0.
Or maybe is it the == that has been hacked to handle bools?
No.
It's that bool is a macro that expands to _Bool and that _Bool variables have special semantics when assigning a value to it.
Is this behaviour portable accross C Standard Library implementations and compilers?
Yes.
What was the correct way of logically comparing two bools before the introduction of stdbool.h ?
When bool is not an _Bool, but like an int, you can convert the values on assignment or comparison to 0 or 1 with double logical NOT:
if (!!a == !!b)
C11, 6.3.1.2 says:
When any scalar value is converted to _Bool, the result is 0 if the
value compares equal to 0; otherwise, the result is 1.
When you assign 4 to b, it's simply assigned to 1. So yes, this behaviour is guaranteed by the C standard.

How to insert booleans into a bitfield in C89

As far as I understand, in C89 all boolean expressions are of type integer. This also means that function parameters that represent bool usually get represented by an int parameter.
Now my question is how I can most ideally take such an int and put it into a bitfield so that it only occupies one bit (let's ignore padding for now).
The first thing here is which type to use. Using int or any other unsigned type doesn't work, because when there is only one bit, only -1 and 0 can be represented (at least with two's complement).
While -1 technically evaluates as true, this is not ideal because actually assigning it without undefined behavior can be quite tricky from what I understand.
So an unsigned type should be chosen for the bitfield:
typedef struct bitfield_with_boolean {
unsigned int boolean : 1;
} bitfield_with_boolean;
The next question is then how to assign that bitfield. Just taking an int or similar won't work because the downcast truncates the value so if the lowest bit wasn't set, a value that would previously evaluate to true would now suddenly evaluate to false.
As far as I understand, the boolean operators are guaranteed to always return either 0 or 1. So my idea to solve this problem would be something like this:
#define to_boolean(expression) (!!(expression))
So in order to assign the value I would do:
bitfield_with_boolean to_bitfield(int boolean) {
bitfield_with_boolean bitfield = {to_boolean(boolean)};
return bitfield;
}
Is that correct, and or is there a better way?
NOTE:
I know the problem is completely solved starting with C99 because casting to _Bool is guaranteed to always result in either a 0 or a 1. Where 0 is only the result if the input had a value of 0.
Yes, your solution is correct. However, I wouldn't hide it behind a macro, and I wouldn't name a macro using all_lowercase letters.
!!var is sufficiently idiomatic that I'd say it's fine in code.
Alternatives include var != 0 and, of course, var ? 1 : 0.

will ~ operator change the data type?

When I read someone's code I find that he bothered to write an explicite type cast.
#define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
When I write code
1 #include<stdio.h>
2 int main(void)
3 {
4 unsigned long int max;
5 max = ~(unsigned long int)0;
6 printf("%lx",max);
7 return 0;
8 }
it works as well. Is it just a meaningless coding style?
The code you read is very bad, for several reasons.
First of all user code should never define ULONG_MAX. This is a reserved identifier and must be provided by the compiler implementation.
That definition is not suitable for use in a preprocessor #if. The _MAX macros for the basic integer types must be usable there.
(unsigned long)0 is just crap. Everybody should just use 0UL, unless you know that you have a compiler that is not compliant with all the recent C standards with that respect. (I don't know of any.)
Even ~0UL should not be used for that value, since unsigned long may (theoretically) have padding bits. -1UL is more appropriate, because it doesn't deal with the bit pattern of the value. It uses the guaranteed arithmetic properties of unsigned integer types. -1 will always be the maximum value of an unsigned type. So ~ may only be used in a context where you are absolutely certain that unsigned long has no padding bits. But as such using it makes no sense. -1 serves better.
"recasting" an expression that is known to be unsigned long is just superfluous, as you observed. I can't imagine any compiler that bugs on that.
Recasting of expression may make sense when they are used in the preprocessor, but only under very restricted circumstances, and they are interpreted differently, there.
#if ((uintmax_t)-1UL) == SOMETHING
..
#endif
Here the value on the left evalues to UINTMAX_MAX in the preprocessor and in later compiler phases. So
#define UINTMAX_MAX ((uintmax_t)-1UL)
would be an appropriate definition for a compiler implementation.
To see the value for the preprocessor, observe that there (uintmax_t) is not a cast but an unknown identifier token inside () and that it evaluates to 0. The minus sign is then interpreted as binary minus and so we have 0-1UL which is unsigned and thus the max value of the type. But that trick only works if the cast contains a single identifier token, not if it has three as in your example, and if the integer constant has a - or + sign.
They are trying to ensure that the type of the value 0 is unsigned long. When you assign zero to a variable, it gets cast to the appropriate type.
In this case, if 0 doesn't happen to be an unsigned long then the ~ operator will be applied to whatever other type it happens to be and the result of that will be cast.
This would be a problem if the compiler decided that 0 is a short or char.
However, the type after the ~ operator should remain the same. So they are being overly cautious with the outer cast, but perhaps the inner cast is justified.
They could of course have specified the correct zero type to begin with by writing ~0UL.

Assign bit field member to char

I have some code here that uses bitsets to store many 1 bit values into a char.
Basically
struct BITS_8 {
char _1:1;
(...)
char _8:1;
}
Now i was trying to pass one of these bits as a parameter into a function
void func(char bit){
if(bit){
// do something
}else{
// do something else
}
}
// and the call was
struct BITS_8 bits;
// all bits were set to 0 before
bits._7 = 1;
bits._8 = 0;
func(bits._8);
The solution was to single the bit out when calling the function:
func(bits._8 & 0x80);
But i kept going into //do something because other bits were set. I was wondering if this is the correct behaviour or if my compiler is broken. The compiler is an embedded compiler that produces code for freescale ASICs.
EDIT: 2 mistakes: the passing of the parameter and that bits._8 should have been 0 or else the error would make no sense.
Clarification
I am interested in what the standard has to say about the assignment
struct X{
unsigned int k:6;
unsigned int y:1;
unsigned int z:1;
}
X x;
x.k = 0;
x.y = 1;
x.z = 0;
char t = X.y;
Should now t contain 1 or b00000010?
I don't think you can set a 1-bit char to 1. That one bit is left to determine whether it's signed or not, so you end up with the difference between 0 and -1.
What you want is an unsigned char, to hide this signing bit. Then you can just use 1s and 0s.
Over the years I've grown a bit suspicious when it comes to these specific compilers, quite often their interpretation of what could be described the finer points of the C standard isn't great. In those cases a more pragmatic approach can help you to avoid insanity, and to get the job done. What this means in this case is that, if the compiler isn't behaving rationally (which you could define as behaving totally different from what gcc does), you help it a bit.
For example you could modify func to become:
void func(char bit){
if(bit & 1){ // mask off everything that's none of its business
// do something
}else{
// do something else
}
}
And wrt your addon question: t should contain 1. It can't contain 10 binary because the variable is only 1 bit wide.
Some reading material from the last publicly available draft for C99
Paragraph 6.7.2.1
4 A bit-field shall have a type that is a qualified or unqualified
version of _Bool, signed int, unsigned int, or some other
implementation-defined type.
(which to me means that the compiler should at least handle your second example correctly) and
9 A bit-field is interpreted as a signed or unsigned integer type
consisting of the specified number of bits.107) If the value 0 or 1 is
stored into a nonzero-width bit-field of type
_Bool, the value of the bit-field shall compare equal to the value stored.
As your compiler is meant for embedded use, where bitfields are a rather important feature, I'd expect their implementation to be correct - if they claim to have bitfields implemented.
I can see why you might want to use char to store flags if Bool is typedef'd to an unsigned int or similar or if your compiler does not support packed enums. You can set up some "flags" using macros (I named them for their place values below, but it makes more sense to name them what they mean) If 8 flags is not enough, this can be extended to other types up to sizeof(type)*8 flags.
/* if you cannot use a packed enum, you can try these macros
* in combination with bit operations on the "flags"
* example printf output is: 1,1,6,4,1
* hopefully the example doesn't make it more confusing
* if so see fvu's example */
#include <stdio.h> /* for printf */
#define ONE ((char) 1)
#define TWO (((char) 1)<<1)
#define FOUR (((char) 1)<<2)
#define EIGHT (((char) 1)<<3)
#define SIXTEEN (((char) 1)<<4)
#define THIRTYTWO (((char) 1)<<5)
#define SIXTYFOUR (((char) 1)<<6)
#define ONETWENTYEIGHT (((char) 1)<<7)
int main(void){
printf("%d,%d,%d,%d,%d\n",ONE & ONE, ONE | ONE, TWO | 6, FOUR & 6, sizeof(ONE));
}
Ok, it was a compiler bug. I wrote the people that produce the compiler and they confirmed it. It only happens if you have a bitfield with an inline function.
Their recommended solution is (if i don't want to wait for a patch)
func((char)bits._8));
The other answers are right about the correct behaviour. Still i'm marking this one as the answer as it is the answer to my problem.

C/GL: Using -1 as sentinel on array of unsigned integers

I am passing an array of vertex indices in some GL code... each element is a GLushort
I want to terminate with a sentinel so as to avoid having to laboriously pass the array length each time alongside the array itself.
#define SENTINEL ( (GLushort) -1 ) // edit thanks to answers below
:
GLushort verts = {0, 0, 2, 1, 0, 0, SENTINEL};
I cannot use 0 to terminate as some of the elements have value 0
Can I use -1?
To my understanding this would wrap to the maximum integer GLushort can represent, which would be ideal.
But is this behaviour guaranteed in C?
(I cannot find a MAX_INT equivalent constant for this type, otherwise I would be using that)
If GLushort is indeed an unsigned type, then (GLushort)-1 is the maximum value for GLushort. The C standard guarantees that. So, you can safely use -1.
For example, C89 didn't have SIZE_MAX macro for the maximum value for size_t. It could be portably defined by the user as #define SIZE_MAX ((size_t)-1).
Whether this works as a sentinel value in your code depends on whether (GLushort)-1 is a valid, non-sentinel value in your code.
GLushort is an UNSIGNED_SHORT type which is typedefed to unsigned short, and which, although C does not guarantee it, OpenGL assumes as a value with a 2^16-1 range (Chapter 4.3 of the specification). On practically every mainstream architecture, this somewhat dangerous assumption holds true, too (I'm not aware of one where unsigned short has a different size).
As such, you can use -1, but it is awkward because you will have a lot of casts and if you forget a cast for example in an if() statement, you can be lucky and get a compiler warning about "comparison can never be true", or you can be unlucky and the compiler will silently optimize the branch out, after which you spend days searching for the reason why your seemingly perfect code executes wrong. Or worse yet, it all works fine in debug builds and only bombs in release builds.
Therefore, using 0xffff as jv42 has advised is much preferrable, it avoids this pitfall alltogether.
I would create a global constant of value:
const GLushort GLushort_SENTINEL = (GLushort)(-1);
I think this is perfectly elegant as long as signed integers are represented using 2's complement.
I don't remember if thats guaranteed by the C standard, but it is virtually guaranteed for most CPU's (in my experience).
Edit: Appparently this is guaranteed by the C standard....
If you want a named constant, you shouldn't use a const qualified variable as proposed in another answer. They are really not the same. Use either a macro (as others have said) or an enumeration type constant:
enum { GLushort_SENTINEL = -1; };
The standard guarantees that this always is an int (really another name of the constant -1) and that it always will translate into the max value of your unsigned type.
Edit: or you could have it
enum { GLushort_SENTINEL = (GLushort)-1; };
if you fear that on some architectures GLushort could be narrower than unsigned int.

Resources