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

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17729
  • 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, 08:24:57 am »
#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 ?
 

Online Psi

  • Super Contributor
  • ***
  • Posts: 9889
  • Country: nz
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #1 on: October 09, 2018, 08:28:34 am »
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, 08:32:05 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17729
  • 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, 08:33:50 am »
Right, perfect, thank you.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #3 on: October 09, 2018, 07:23:41 pm »
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: 814
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #4 on: October 09, 2018, 07:38:03 pm »
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: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #5 on: October 09, 2018, 08:01:53 pm »
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 SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17729
  • 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 09, 2018, 08:06:59 pm »
i don't bother with bool's as it's an 8 bit CPU anyway so nothing gained.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #7 on: October 09, 2018, 08:29:37 pm »
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.


 

Online newbrain

  • Super Contributor
  • ***
  • Posts: 1714
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #8 on: October 10, 2018, 06:58:31 am »
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, 07:21:16 am by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8106
  • Country: fi
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #9 on: October 10, 2018, 07:08:50 am »
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.
 

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3452
  • Country: it
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #10 on: October 10, 2018, 07:32:15 am »
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: 163
  • Country: au
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #11 on: October 10, 2018, 02:57:03 pm »
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: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #12 on: October 10, 2018, 03:24:35 pm »
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;
 

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3452
  • Country: it
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #13 on: October 10, 2018, 03:29:10 pm »
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: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #14 on: October 10, 2018, 03:46:27 pm »
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: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #15 on: October 10, 2018, 04:01:09 pm »
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 10, 2018, 04:04:34 pm by SiliconWizard »
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #16 on: October 10, 2018, 04:18:10 pm »
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: 814
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #17 on: October 10, 2018, 05:32:03 pm »
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: 8106
  • Country: fi
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #18 on: October 10, 2018, 06:12:24 pm »
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: 814
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #19 on: October 10, 2018, 06:19:48 pm »
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: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #20 on: October 10, 2018, 06:23:56 pm »
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: 14297
  • Country: fr
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #21 on: October 10, 2018, 06:33:54 pm »
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: 814
  • Country: se
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #22 on: October 10, 2018, 06:38:15 pm »
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

Online JPortici

  • Super Contributor
  • ***
  • Posts: 3452
  • Country: it
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #23 on: October 10, 2018, 08:38:17 pm »
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: :)
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4391
  • Country: dk
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #24 on: October 10, 2018, 09:36:37 pm »
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
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #25 on: October 10, 2018, 11:24:15 pm »
ARM missed the chance to add true single-bit variables as a extension to their compilers, in conjunction with the "bit-banding" hardware feature.
It could've worked really nicely - pointers to single bits would have worked fine, and everything.But it would have been non-standards-conforming, and seemed to mostly be aimed at IO ports that were better handled via other mechanisms, so they left it for users to do on their own, and so it mostly "didn't happen."  And now most new ARMs don't even implement bit-banding, so the the opportunity is gone...
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4391
  • Country: dk
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #26 on: October 10, 2018, 11:37:58 pm »
ARM missed the chance to add true single-bit variables as a extension to their compilers, in conjunction with the "bit-banding" hardware feature.
It could've worked really nicely - pointers to single bits would have worked fine, and everything.But it would have been non-standards-conforming, and seemed to mostly be aimed at IO ports that were better handled via other mechanisms, so they left it for users to do on their own, and so it mostly "didn't happen."  And now most new ARMs don't even implement bit-banding, so the the opportunity is gone...

afaiu bit banding was dropped because it doesn't play well with data caches
 

Offline tombi

  • Regular Contributor
  • *
  • Posts: 163
  • Country: au
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #27 on: October 10, 2018, 11:52:13 pm »
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.

No! Very much not what I meant. I think that using bool adds readability and might even provide a speed-up as the compiler can make assumptions about bool types (i.e. they are effectively just a single bit).

I'd go further in fact and advocate explicit conversions so for example if you have an expression that is non-boolean, (like the result of a bit mask operation) then I think it is good to explicitly convert it to a boolean value by comparing it with zero. This means you are doing the conversion where you choose and you reduce the chance of weird operator precedence issues like it multiplying a number by a the result of a boolean expression.

Tom

 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 3996
  • Country: nz
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #28 on: October 11, 2018, 03:46:08 am »
#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 ?

If you want to get a result of only 00000000 or 00000001 then use this instead:

Code: [Select]
#define BIT_GET(p,m) (((p)>>(m)) & 1)

That's a bit more work for the CPU as the shift is done at run time instead of compile time. If you've got a proper multi-bit shifter then it's likely to be only one extra instruction/cycle and so not to be worried about.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #29 on: October 11, 2018, 04:41:06 am »
Quote
#define BIT_GET(p,m) (((p)>>(m)) & 1)
That's a bit more work for the CPU as the shift is done at run time instead of compile time.
If m is a constant, the compiler will optimize weirdly for you...
Code: [Select]
bool get_b6() {
    return BIT_GET(PORTB, 6);
   0:   85 b1           in      r24, 0x05   ;; read portb
   2:   86 fb           bst     r24, 6        ;; set T status bit from bit 6
   4:   88 27           eor     r24, r24    ;; zero return value
   6:   80 f9           bld     r24, 0        ;; load bit 0 (true or false) from T
   8:   08 95           ret
I get versions using a shift & and (b1), just an and (b0), and the carry bit (b7)


Quote
If you've got a proper multi-bit shifter then it's likely to be only one extra instruction/cycle and so not to be worried about.
Alas, no "proper" shifter on any of the AVR chips.  going to a variable bit number gets you a loop.  Computed with a 16bit int, too.  Sad.
Code: [Select]
bool get_bv(uint8_t b) {
    return BIT_GET(PORTB,b);
  2c:   25 b1           in      r18, 0x05       ; 5
  2e:   30 e0           ldi     r19, 0x00       ; 0
  30:   a9 01           movw    r20, r18
  32:   00 c0           rjmp    38
  34:   55 95           asr     r21
  36:   47 95           ror     r20
  38:   8a 95           dec     r24
  3a:   02 f4           brpl   34
  3c:   ca 01           movw    r24, r20
  3e:   81 70           andi    r24, 0x01       ; 1
  40:   08 95           ret

 

Offline tombi

  • Regular Contributor
  • *
  • Posts: 163
  • Country: au
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #30 on: October 11, 2018, 05:01:43 am »

Why not

Code: [Select]
#define BIT_GET(p,m) ( (p) & (BIT(m)) != 0 )
#define BIT(x) (0x01 << (x))
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #31 on: October 11, 2018, 05:47:30 am »
Needs another set of parens, after which it produces exactly the same code (for AVR) as the previous macro.
 

Offline tombi

  • Regular Contributor
  • *
  • Posts: 163
  • Country: au
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #32 on: October 11, 2018, 05:55:22 am »
Ok yes brackets...

Reasonably surprised that the generated code is the same as the previous definition -  #define BIT_GET(p,m) (((p)>>(m)) & 1).

The BIT() macro should evaluate to a compiler constant.

Then BIT_GET(p,m) assuming M is a constant evaluates to ((p & constant) != 0)

I only suggest adding the !=0 as then the result is a boolean and not a number.

So I assume it is used like

if ( BIT_GET(something,BIT(3))  )
{
...


 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #33 on: October 11, 2018, 06:42:09 am »
yep.  As you say.  The macros evaluate to the same code on AVR, CM0, and CM4. (all gcc, so that's not really surprising.)CM4 ends up using the "bit field extract" instruction, which is pretty nice.
here's code that should be pretty platform-independent:
Code: [Select]
#include <stdint.h>

volatile uint8_t PORTB;

#define BIT_GET(p,m) ( ((p) & (BIT(m))) != 0 )
#define BIT(x) (0x01 << (x))

#define BIT_GET1(p,m) ((((uint8_t)p)>>((uint8_t)m)) & (uint8_t)1)

bool get_b3() {
    return BIT_GET(PORTB, 3);
}
bool get1_b3() {
    return BIT_GET1(PORTB, 3);
}

bool get_bv(uint8_t b) {
    return BIT_GET(PORTB,b);
}
bool get1_bv(uint8_t b) {
    return BIT_GET1(PORTB,b);
}

int main() {}
extern "C" { void _exit(int c) {while(1);} }
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 822
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #34 on: October 11, 2018, 09:32:51 am »
Code: [Select]
#include <stdint.h>
#include <stdbool.h>
static inline bool bit_get(volatile uint8_t* p, uint8_t b){
    return *p & (1<<b) ? 1 : 0;
}
static inline void bit_set(volatile uint8_t* p, uint8_t b, bool tf){
    if(tf) *p |= (1<<b); else *p &= ~(1<<b);
}
void main()
{
    //just guessing that 0x24 will get me porta, 0x25 portb (IN/OUT instructions)
    //PORTA.3 = PORTB.6
    bit_set((volatile uint8_t*)0x24, 3, bit_get((volatile uint8_t*)0x25,6));

    for(;;);
}
/*
Disassembly of section .text:

00000000 <main>:
   0:   2e 9b           sbis    0x05, 6 ; 5
   2:   02 c0           rjmp    .+4             ; 0x8 <__zero_reg__+0x7>
   4:   23 9a           sbi     0x04, 3 ; 4
   6:   01 c0           rjmp    .+2             ; 0xa <__zero_reg__+0x9>
   8:   23 98           cbi     0x04, 3 ; 4
   a:   ff cf           rjmp    .-2             ; 0xa <__zero_reg__+0x9>
*/
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4196
  • Country: us
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #35 on: October 11, 2018, 09:50:45 am »
Yeah; except your use of inlines, and compiler optimization, means that you never actually have a "bool."
I figure I'm a bit upset that I don't get:
Code: [Select]
   ldi r24, 1        ;; assume true   sbis PORTB,6  ;; test IO bit
    xor r24, r24   ;; we were wrong; set false.   ret
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 822
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #36 on: October 11, 2018, 11:48:31 am »
Quote
bool sw_is_on()
{
    return bit_get((volatile uint8_t*)0x25, 6);
}

/*
00000000 <sw_is_on>:
   0:   85 b1           in      r24, 0x05       ; 5
   2:   86 fb           bst     r24, 6
   4:   88 27           eor     r24, r24
   6:   80 f9           bld     r24, 0
   8:   08 95           ret
exact same result as the macro
 

Offline ahbushnell

  • Frequent Contributor
  • **
  • Posts: 734
  • Country: us
Re: [gcc C] I have been blindly doing this but how does it work
« Reply #37 on: October 13, 2018, 07:18:13 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 ?
Its bit wise.  So each bit is operated on by its position.

Sent from my SM-G930V using Tapatalk

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf