Author Topic: [gcc C] I have been blindly doing this but how does it work  (Read 1554 times)

0 Members and 1 Guest are viewing this topic.

Offline Simon

  • Global Moderator
  • *****
  • Posts: 12084
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
[gcc C] I have been blindly doing this but how does it work
« on: October 09, 2018, 07:24:57 pm »
#define BIT_GET(p,m) ((p) & (BIT(m)))
#define BIT(x) (0x01 << (x))

So I get the bit masking stuff but but how is some random byte that is the result is understood as a boolean state.

So 01010101 & 00000100 = 00000100

How does 00000100 equate the Boolean state of 1 ?
https://www.simonselectronics.co.uk/shop New stock now in of EEVblog Brymen 235 and uCurrent Gold, Now selling a selection of Probe Master probes
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 6428
  • Country: nz
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #1 on: October 09, 2018, 07:28:34 pm »
All numbers are interpreted as boolean 1, except zero which is boolean 0

eg, these will loop forever because 4 is evaluated as true (1)

while (4)
{

}

while (0b00000100)
{

}
« Last Edit: October 09, 2018, 07:32:05 pm by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 12084
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #2 on: October 09, 2018, 07:33:50 pm »
Right, perfect, thank you.
https://www.simonselectronics.co.uk/shop New stock now in of EEVblog Brymen 235 and uCurrent Gold, Now selling a selection of Probe Master probes
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #3 on: October 10, 2018, 06:23:41 am »
Yes - what you did is thus perfectly legit.
There is no boolean type per se in C.  Any integer different from 0 is considered true in any conditional statement, and any integer equal to 0 is false.

I often write conditions such as "xxx & MASK". They are compact and readable.

A corollary (and pitfall for people used to C++ only for instance) of this is that you should never assume any C expression used as a condition to be exactly 1 when true, or any other magic value. It can be any value other than zero.

One common way of "normalizing" a boolean expression in C is to use a double logic negation: if you write "!!(xxx & MASK)" you should get exactly either 0 or 1. I've seen this in various source codes. Note that it's absolutely not required, as manipulating the result value of a condition makes no sense to me. Some people may be tempted to use this in an attempt to optimize expressions (for instance multiplying a "boolean" value within some expression so as to avoid using an explicit test), but I consider this obfuscating, and decent modern compilers will make optimizations that are much better than those hand-written tricks anyway.

 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 677
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #4 on: October 10, 2018, 06:38:03 am »
There is no boolean type per se in C.
Since 1999 you can include stdbool.h to enable the bool type. This type can only have the value of 0 or 1.
 
The following users thanked this post: newbrain

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #5 on: October 10, 2018, 07:01:53 am »
Yes, but this is essentially sugar coating. Conditional expressions can still be plain integers. And I've just re-checked the standard: there's nothing there that I've seen that actually guarantees by standard that a 'bool' variable will hold only 0 or 1 either. It may or may not depending on the compiler's implementation as far as I've understood it. The header just declares a macro 'bool' that expands to '_Bool'.
The standard only states that "The type_Bool and  the  unsigned  integer  types  that  correspond  to  the  standard  signed  integer types  are  the standard unsigned  integer types." and that "An object declared as type _Bool is large enough to store the values 0 and 1." Large enough doesn't mean "only". Nothing prevents the compiler from just using an unsigned integer as _Bool (as is suggested in the other sentence). Just states that it should be at least 1 bit wide ;)

Having tested it on GCC, GCC actually seems to reduce values to 0 or 1 on bool assignments, but I don't think it's required. I'm taking this from the C 2011 std though, so that may have evolved a bit.

I've actually been using this type for years now, but essentially to convey meaning and improve readability. It doesn't change squat to the behavior as far as I'm concerned. And again, expecting a specific integer value for a bool would be neither wise nor readable IMHO.
 

Offline Simon

  • Global Moderator
  • *****
  • Posts: 12084
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #6 on: October 10, 2018, 07:06:59 am »
i don't bother with bool's as it's an 8 bit CPU anyway so nothing gained.
https://www.simonselectronics.co.uk/shop New stock now in of EEVblog Brymen 235 and uCurrent Gold, Now selling a selection of Probe Master probes
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #7 on: October 10, 2018, 07:29:37 am »
i don't bother with bool's as it's an 8 bit CPU anyway so nothing gained.

I'd still suggest using the bool type for boolean value storage as this has become part of the standard and will be easier to read than using the pervasive "int" instead that we used to use. But other than that, it doesn't change much. I find it more readable though. But again, I strongly advise against assuming that it will get any particular value.

In the same vein, I strongly suggest using the stdint.h header and the standard integer types in it, especially in embedded software. They have added a much-needed standard way of declaring variables with exact bit width and signedness (such as 'uint8_t', etc), whereas before that we used all kinds of tricks for that that were largely non-portable.

Concerning the macros that you submitted, that doesn't change anything at all. They are still valid and no mention of the bool type is necessary. So the bool type is mainly for variable/struct members declaration.


 

Offline newbrain

  • Frequent Contributor
  • **
  • Posts: 610
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #8 on: October 10, 2018, 05:58:31 pm »
And I've just re-checked the standard: there's nothing there that I've seen that actually guarantees by standard that a 'bool' variable will hold only 0 or 1 either.

6.3.1.2 would seem pretty clear to me.  :-//

Quote
6.3.1.2  Boolean type
When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.

But of course:
Code: [Select]
bool b;
*(uint8_t *)&b = 123;

I would say that's UB, though (I have to check).

EtA: I have checked, 6.5 clause 7, first bullet.

« Last Edit: October 10, 2018, 06:21:16 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 1367
  • Country: fi
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #9 on: October 10, 2018, 06:08:50 pm »
I'd still suggest using the bool type for boolean value storage as this has become part of the standard and will be easier to read than using the pervasive "int" instead that we used to use.

... or at least don't use "int" on 8-bitters unless you are sure about what you are doing - it's likely to be reproduced as 16-bit integer, as the C standard requires IIRC, with the obvious overhead of software emulation of 16-bit arithmetic, and memory consumption. If it's a volatile used to pass information between the ISR and the main loop, the compiler doesn't even have a chance to optimize it. And then if you make the mistake to expect it's atomic, like the 8-bit bool would be...  |O

Quote
In the same vein, I strongly suggest using the stdint.h header and the standard integer types in it, especially in embedded software.

Yes, 110% this. Even if you don't end up using bool, you need standard readable types of integers. The options are, define your own (like we did before the standard existed) in your own header, or use the standard way of stdint or inttypes.
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 2283
  • Country: it
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #10 on: October 10, 2018, 06:32:15 pm »
i don't bother with bool's as it's an 8 bit CPU anyway so nothing gained.

you gain in readability. I am gradually updating all the old firmwares to remove every bit of assembly that don't compromize functionality, every implicit bitfield converted to a bitfield structure and so on.
 

Offline tombi

  • Regular Contributor
  • *
  • Posts: 149
  • Country: au
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #11 on: October 11, 2018, 01:57:03 am »
Actually some compilers (like the Microsoft dinosaur I use for work) will give you a ‘performance warning’ if you assign an int to a bool. I think the compiler uses some tricks to make manipulating bool types faster.

So I also agree - use the bool type for booleans and not just because it make the code make sense.

Tom


Sent from my iPhone using Tapatalk
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #12 on: October 11, 2018, 02:24:35 am »
Quote
6.3.1.2  Boolean type
When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.

True. The key is that it needs a conversion to do this. The underlying storage itself can be as wide as the compiler wants, making it thus possible that a "bool" declared variable would hold something else than 1 or 0 in some cases.

My point is that IMO, it's bad practice to assume only 0 or 1 for a conditional expression in C in general, and integer expressions that are not of type 'bool' are still valid in C as conditions. Thus I happen to actually not care and not *want* to care. I still think this is some kind of sugar coating as C doesn't strictly *require* a boolean-type expression for conditions, so it's only half-integrated in the C language IMO (obviously not to break existing code, so it makes perfect sense). Now if it was required as in very strongly-typed languages such as ADA, that would be another story.

My biggest pet peave with "boolean" expressions in C is as I mentioned the "trick" expressions that could be encouraged by this and that are hard to read, would break in non-compliant compilers and should be avoided at all costs IMO (optimizers being much more efficient for this anyway):
Code: [Select]
bool b = W & MASK;
int n = b*10 + 1;
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 2283
  • Country: it
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #13 on: October 11, 2018, 02:29:10 am »
My point is that IMO, it's bad practice to assume only 0 or 1 for a conditional expression in C in general, and integer expressions that are not of type 'bool' are still valid in C as conditions. Thus I happen to actually not care and not *want* to care. I still think this is some kind of sugar coating as C doesn't strictly *require* a boolean-type expression for conditions, so it's only half-integrated in the C language IMO

stdbool.h in XC8 V2.00 has
#define false 0
#define true !false
:)

i havent' checked in other compilers but i don't expect to see anything different
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #14 on: October 11, 2018, 02:46:27 am »
Small example:
Code: [Select]
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>

int main(void)
{
bool b1;
union { bool b; int n; } b2;

b1 = 25;

printf("b1 = %d\n", b1);
printf("sizeof b1 = %"PRIu64"\n", sizeof b1);

b2.n = 10;

printf("b2.b = %d\n", b2.b);
}

On an x64 target with GCC gives:

Code: [Select]
b1 = 1
sizeof b1 = 1
b2.b = 10

Implicit conversions are only done while assigning bool variables.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #15 on: October 11, 2018, 03:01:09 am »
stdbool.h in XC8 V2.00 has
#define false 0
#define true !false

Not sure you got the main point. First because those are just constants that are guaranteed to be seen as either false or true in logic/conditional expressions, nothing more. Second because those macros are valid even for very old versions of C. This is exactly how TRUE and FALSE constants have been declared in lots of various C headers for decades. Obviously those declarations are correct: they are just tautologies. Not false is true, not true is false. And 0 is false in C. What else does it actually say? :D

Again there is no bijection in C between the "true" logic state and the value "1". There only is for the "0" value.
There kind of is a bijection if you strictly stay in the realm of 'bool'-typed expressions with C >= 99, with pitfalls. And again, I personally don't care and think this is something that should have been avoided in the C standard, for reasons given above and mostly because it leaves an inconsistency (again since any value other than 0 in C is still considered true, even pointers). A true boolean type integrated in C should have prevented IMO any implicit conversion from any other type (and only allow expressions with bool values and logic operators). Just my opinion of course. Again they have obviously chosen a compromise not to break existing code, thus the half-baked solution.

« Last Edit: October 11, 2018, 03:04:34 am by SiliconWizard »
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #16 on: October 11, 2018, 03:18:10 am »
Actually some compilers (like the Microsoft dinosaur I use for work) will give you a ‘performance warning’ if you assign an int to a bool. I think the compiler uses some tricks to make manipulating bool types faster.

If the compiler in question supports the bool type and C99, it's not completely a dinosaur. Microsoft's older compilers are known not to support C99 very well though, or only partially.

In your example, the warning makes perfect sense and I think you considered it backwards. As newbrain pointed out and I discussed afterwards (and showed an example), assigning an integer to a bool will do an implicit conversion and thus will "clip" the integer value to one if it's different from zero. This clipping operation costs more than a simple assignment. Thus the performance warning.

Due to this, depending on the compiler and the assignments/expressions that are used, using the bool type may thus actually be less efficient than keeping your logic expressions as integers.

Again, it mostly adds to readability, prevents (or should) developers from declaring their own boolean types all over the place, and may have been a decision to sort of bridge a gap between C and C++ concerning boolean values, but not much more. Any decent optimizer will optimize your logic expressions probably just as well if you don't use the bool type. As seen above, most compilers (GCC does at least) will store 'bool' variables as 8-bit integers (although it's not strictly required, but makes sense) though, and thus they will take less storage space than an 'int' on most targets, so that can be a plus.
 
The following users thanked this post: newbrain

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 677
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #17 on: October 11, 2018, 04:32:03 am »
Code: [Select]
b2.n = 10;

printf("b2.b = %d\n", b2.b);
.
Storing something in a union member and retrieving it from a different member invokes undefined behavior. Anything can happen, so I don't know what this example was supposed to prove.
 
The following users thanked this post: newbrain

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 1367
  • Country: fi
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #18 on: October 11, 2018, 05:12:24 am »
Storing something in a union member and retrieving it from a different member invokes undefined behavior. Anything can happen, so I don't know what this example was supposed to prove.

Yeah, per standard. And standard is just paper.

Yes, demons may fly out of your nose. In theory.

In reality, unions are used exactly for this purpose so widely, that every attempt to make a compiler break the existing software gets immediate backlash. This has been the case for decades - especially in embedded.

Union is simply really useful for this purpose.

More discussion here: https://stackoverflow.com/questions/252552/why-do-we-need-c-unions - the best accepted answer agrees with my viewpoint.

But I guess this is a so-called "opinion" thing and I respect anyone's idea of adhering to the standard to the letter.
 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 677
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #19 on: October 11, 2018, 05:19:48 am »
What happens down the line with this bool with a value of 10? The compiler is free to optimize the use of the bool and might generate code that only looks at bit 0.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #20 on: October 11, 2018, 05:23:56 am »
Yes in practice this has been so widely used that no compiler that I've ever run into would try and map union fields on different offsets. So this is basically equivalent to using pointers. If you're going to get stuck up about it, you may even say that I made assumptions as to the endianness. The exact result doesn't matter anyway.

Although it didn't really even need to be proven, it just shows that a bool declared variable may contain many other values than 0 and 1 and that again, the bool type in C is not much more than sugar coating. For the rest of my point read above.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 1003
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #21 on: October 11, 2018, 05:33:54 am »
What happens down the line with this bool with a value of 10? The compiler is free to optimize the use of the bool and might generate code that only looks at bit 0.

For constant values, the "optimization" will occur at compile time anyway, not at run time.

The compiler is free to do whatever it wants if you only use bool's in conditions (same as with plain int expressions). If you use bool's values in arithmetic expression such as the example I gave, it's not. It will coerce it into 0 or 1. Again I find this madness to do so anyway.

As for the above example of 10, I'm afraid looking at bit 0 won't tell you much as 10 is "true" in the C logic sense yet its bit 0 is 0. But that's just a detail. Point is, yes optimizers will still do whatever they want/can to simplify expressions in ways that may be far away from what you would by hand.

 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 677
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #22 on: October 11, 2018, 05:38:15 am »
Although it didn't really even need to be proven, it just shows that a bool declared variable may contain many other values than 0 and 1 and that again, the bool type in C is not much more than sugar coating.
I didn't argue that something odd would happen inside the union. I fully expect the bool to "have" the value 10 in the example. What I am arguing is that the compiler is free to assume the bool will never have a value other than 0 and 1. Going behind the back of the compiler to set bits ad hoc can lead to problems, both for bool, pointers and other data types.
 
The following users thanked this post: newbrain

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 2283
  • Country: it
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #23 on: October 11, 2018, 07:38:17 am »
stdbool.h in XC8 V2.00 has
#define false 0
#define true !false

Not sure you got the main point. First because those are just constants that are guaranteed to be seen as either false or true in logic/conditional expressions, nothing more. Second because those macros are valid even for very old versions of C. This is exactly how TRUE and FALSE constants have been declared in lots of various C headers for decades. Obviously those declarations are correct: they are just tautologies. Not false is true, not true is false. And 0 is false in C. What else does it actually say? :D

Again there is no bijection in C between the "true" logic state and the value "1". There only is for the "0" value.
There kind of is a bijection if you strictly stay in the realm of 'bool'-typed expressions with C >= 99, with pitfalls. And again, I personally don't care and think this is something that should have been avoided in the C standard, for reasons given above and mostly because it leaves an inconsistency (again since any value other than 0 in C is still considered true, even pointers). A true boolean type integrated in C should have prevented IMO any implicit conversion from any other type (and only allow expressions with bool values and logic operators). Just my opinion of course. Again they have obviously chosen a compromise not to break existing code, thus the half-baked solution.



of course i got it, i was just :horse: :)
 

Online langwadt

  • Frequent Contributor
  • **
  • Posts: 971
  • Country: dk
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #24 on: October 11, 2018, 08:36:37 am »
i don't bother with bool's as it's an 8 bit CPU anyway so nothing gained.

I don't see why it couldn't gain something on some platforms where the compiler could use bits to store bools and bitwise instructions to manipulate them
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf