EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Fundamental C question about "if" statements

Started by Oltimer September 20, 2015
Learning some embedded C using Microchip's C18 Lite.


I tried the following and it misbehaved:

if( 10 < my_variable < 20 )
	{ //do this......}



Using the following works:

if (( x > 10) & ( x < 20))
	{ //do this.....}



Is it normal that C cannot handle complexities such as "a < b < c" ?
I would have thought a compiler could easily work out what was intended.

Thanks.
On 20/09/15 13:22, Oltimer wrote:
> > Learning some embedded C using Microchip's C18 Lite. > > > I tried the following and it misbehaved: > > if( 10 < my_variable < 20 ) > { //do this......} > > > > Using the following works: > > if (( x > 10) & ( x < 20)) > { //do this.....} > > > > Is it normal that C cannot handle complexities such as "a < b < c" ? > I would have thought a compiler could easily work out what was intended. > > Thanks.
No, compilers cannot work out something like "a < b < c" - it is interpreted as though it were "(a < b) < c", where "(a < b)" is either 0 or 1. A compiler is merely a computer program that follows set rules - it is not human, and cannot apply common sense to interpret what you write. Your second version is also wrong. In C, the "&" operator is a bitwise and - what you want is a logical and which is "&&". In a number of circumstances, such as this one, they have the same logical effect - but don't make that mistake. Learn the difference, and use the correct version. (The same applies to bitwise or | and logical or || ). So the correct version is : if ((x > 10) && (x < 20)) { // Do this... } You'll get the hang of it - just don't assume C is normal mathematics, and be careful to be accurate about what you write.
On 20-Sep-15 7:37 PM, David Brown wrote:
> On 20/09/15 13:22, Oltimer wrote: >> >> Learning some embedded C using Microchip's C18 Lite. >> >> >> I tried the following and it misbehaved: >> >> if( 10 < my_variable < 20 ) >> { //do this......} >> >> >> >> Using the following works: >> >> if (( x > 10) & ( x < 20)) >> { //do this.....} >> >> >> >> Is it normal that C cannot handle complexities such as "a < b < c" ? >> I would have thought a compiler could easily work out what was intended. >> >> Thanks. > > No, compilers cannot work out something like "a < b < c" - it is > interpreted as though it were "(a < b) < c", where "(a < b)" is either 0 > or 1. A compiler is merely a computer program that follows set rules - > it is not human, and cannot apply common sense to interpret what you write. > > Your second version is also wrong. In C, the "&" operator is a bitwise > and - what you want is a logical and which is "&&". In a number of > circumstances, such as this one, they have the same logical effect - but > don't make that mistake. Learn the difference, and use the correct > version. (The same applies to bitwise or | and logical or || ). > > So the correct version is : > > if ((x > 10) && (x < 20)) { > // Do this... > } > > You'll get the hang of it - just don't assume C is normal mathematics, > and be careful to be accurate about what you write. >
Thanks David. The reassurance I'm on the right track is good. Yes, looking at it I can see that it should be "&&" Thanks again!
On 9/20/15 7:37 AM, David Brown wrote:
> > No, compilers cannot work out something like "a < b < c" - it is > interpreted as though it were "(a < b) < c", where "(a < b)" is either 0 > or 1. A compiler is merely a computer program that follows set rules - > it is not human, and cannot apply common sense to interpret what you write. >
There are some computer languages that do allow a < b < c (like python). The key point here is that C does not define the ability to do this as a special case of the syntax.
On 9/20/2015 8:13 AM, Oltimer wrote:
> On 20-Sep-15 7:37 PM, David Brown wrote: >> On 20/09/15 13:22, Oltimer wrote: >>> >>> Learning some embedded C using Microchip's C18 Lite. >>> >>> >>> I tried the following and it misbehaved: >>> >>> if( 10 < my_variable < 20 ) >>> { //do this......} >>> >>> >>> >>> Using the following works: >>> >>> if (( x > 10) & ( x < 20)) >>> { //do this.....} >>> >>> >>> >>> Is it normal that C cannot handle complexities such as "a < b < c" ? >>> I would have thought a compiler could easily work out what was intended. >>> >>> Thanks. >> >> No, compilers cannot work out something like "a < b < c" - it is >> interpreted as though it were "(a < b) < c", where "(a < b)" is either 0 >> or 1. A compiler is merely a computer program that follows set rules - >> it is not human, and cannot apply common sense to interpret what you >> write. >> >> Your second version is also wrong. In C, the "&" operator is a bitwise >> and - what you want is a logical and which is "&&". In a number of >> circumstances, such as this one, they have the same logical effect - but >> don't make that mistake. Learn the difference, and use the correct >> version. (The same applies to bitwise or | and logical or || ). >> >> So the correct version is : >> >> if ((x > 10) && (x < 20)) { >> // Do this... >> } >> >> You'll get the hang of it - just don't assume C is normal mathematics, >> and be careful to be accurate about what you write. >> > > > Thanks David. The reassurance I'm on the right track is good. > > Yes, looking at it I can see that it should be "&&"
Confusing & with && is a common mistake as is mixing = with ==. Both can be hard to debug too. -- Rick
On 20/09/15 15:30, rickman wrote:
> On 9/20/2015 8:13 AM, Oltimer wrote: >> On 20-Sep-15 7:37 PM, David Brown wrote: >>> On 20/09/15 13:22, Oltimer wrote: >>>> >>>> Learning some embedded C using Microchip's C18 Lite. >>>> >>>> >>>> I tried the following and it misbehaved: >>>> >>>> if( 10 < my_variable < 20 ) >>>> { //do this......} >>>> >>>> >>>> >>>> Using the following works: >>>> >>>> if (( x > 10) & ( x < 20)) >>>> { //do this.....} >>>> >>>> >>>> >>>> Is it normal that C cannot handle complexities such as "a < b < c" ? >>>> I would have thought a compiler could easily work out what was >>>> intended. >>>> >>>> Thanks. >>> >>> No, compilers cannot work out something like "a < b < c" - it is >>> interpreted as though it were "(a < b) < c", where "(a < b)" is either 0 >>> or 1. A compiler is merely a computer program that follows set rules - >>> it is not human, and cannot apply common sense to interpret what you >>> write. >>> >>> Your second version is also wrong. In C, the "&" operator is a bitwise >>> and - what you want is a logical and which is "&&". In a number of >>> circumstances, such as this one, they have the same logical effect - but >>> don't make that mistake. Learn the difference, and use the correct >>> version. (The same applies to bitwise or | and logical or || ). >>> >>> So the correct version is : >>> >>> if ((x > 10) && (x < 20)) { >>> // Do this... >>> } >>> >>> You'll get the hang of it - just don't assume C is normal mathematics, >>> and be careful to be accurate about what you write. >>> >> >> >> Thanks David. The reassurance I'm on the right track is good. >> >> Yes, looking at it I can see that it should be "&&" > > Confusing & with && is a common mistake as is mixing = with ==. Both > can be hard to debug too. >
Make heavy use of whatever warnings your compiler can give you - gcc with lots of warnings can pick up on many such cases.
On 9/20/2015 10:13 AM, David Brown wrote:
> On 20/09/15 15:30, rickman wrote: >> On 9/20/2015 8:13 AM, Oltimer wrote: >>> On 20-Sep-15 7:37 PM, David Brown wrote: >>>> On 20/09/15 13:22, Oltimer wrote: >>>>> >>>>> Learning some embedded C using Microchip's C18 Lite. >>>>> >>>>> >>>>> I tried the following and it misbehaved: >>>>> >>>>> if( 10 < my_variable < 20 ) >>>>> { //do this......} >>>>> >>>>> >>>>> >>>>> Using the following works: >>>>> >>>>> if (( x > 10) & ( x < 20)) >>>>> { //do this.....} >>>>> >>>>> >>>>> >>>>> Is it normal that C cannot handle complexities such as "a < b < c" ? >>>>> I would have thought a compiler could easily work out what was >>>>> intended. >>>>> >>>>> Thanks. >>>> >>>> No, compilers cannot work out something like "a < b < c" - it is >>>> interpreted as though it were "(a < b) < c", where "(a < b)" is >>>> either 0 >>>> or 1. A compiler is merely a computer program that follows set rules - >>>> it is not human, and cannot apply common sense to interpret what you >>>> write. >>>> >>>> Your second version is also wrong. In C, the "&" operator is a bitwise >>>> and - what you want is a logical and which is "&&". In a number of >>>> circumstances, such as this one, they have the same logical effect - >>>> but >>>> don't make that mistake. Learn the difference, and use the correct >>>> version. (The same applies to bitwise or | and logical or || ). >>>> >>>> So the correct version is : >>>> >>>> if ((x > 10) && (x < 20)) { >>>> // Do this... >>>> } >>>> >>>> You'll get the hang of it - just don't assume C is normal mathematics, >>>> and be careful to be accurate about what you write. >>>> >>> >>> >>> Thanks David. The reassurance I'm on the right track is good. >>> >>> Yes, looking at it I can see that it should be "&&" >> >> Confusing & with && is a common mistake as is mixing = with ==. Both >> can be hard to debug too. >> > > Make heavy use of whatever warnings your compiler can give you - gcc > with lots of warnings can pick up on many such cases.
Yeah, another common mistake is thinking warnings are just "warnings". Code so that there are none. -- Rick
On 20/09/15 17:14, rickman wrote:
> On 9/20/2015 10:13 AM, David Brown wrote: >> On 20/09/15 15:30, rickman wrote: >>> On 9/20/2015 8:13 AM, Oltimer wrote: >>>> On 20-Sep-15 7:37 PM, David Brown wrote: >>>>> On 20/09/15 13:22, Oltimer wrote: >>>>>> >>>>>> Learning some embedded C using Microchip's C18 Lite. >>>>>> >>>>>> >>>>>> I tried the following and it misbehaved: >>>>>> >>>>>> if( 10 < my_variable < 20 ) >>>>>> { //do this......} >>>>>> >>>>>> >>>>>> >>>>>> Using the following works: >>>>>> >>>>>> if (( x > 10) & ( x < 20)) >>>>>> { //do this.....} >>>>>> >>>>>> >>>>>> >>>>>> Is it normal that C cannot handle complexities such as "a < b < c" ? >>>>>> I would have thought a compiler could easily work out what was >>>>>> intended. >>>>>> >>>>>> Thanks. >>>>> >>>>> No, compilers cannot work out something like "a < b < c" - it is >>>>> interpreted as though it were "(a < b) < c", where "(a < b)" is >>>>> either 0 >>>>> or 1. A compiler is merely a computer program that follows set >>>>> rules - >>>>> it is not human, and cannot apply common sense to interpret what you >>>>> write. >>>>> >>>>> Your second version is also wrong. In C, the "&" operator is a >>>>> bitwise >>>>> and - what you want is a logical and which is "&&". In a number of >>>>> circumstances, such as this one, they have the same logical effect - >>>>> but >>>>> don't make that mistake. Learn the difference, and use the correct >>>>> version. (The same applies to bitwise or | and logical or || ). >>>>> >>>>> So the correct version is : >>>>> >>>>> if ((x > 10) && (x < 20)) { >>>>> // Do this... >>>>> } >>>>> >>>>> You'll get the hang of it - just don't assume C is normal mathematics, >>>>> and be careful to be accurate about what you write. >>>>> >>>> >>>> >>>> Thanks David. The reassurance I'm on the right track is good. >>>> >>>> Yes, looking at it I can see that it should be "&&" >>> >>> Confusing & with && is a common mistake as is mixing = with ==. Both >>> can be hard to debug too. >>> >> >> Make heavy use of whatever warnings your compiler can give you - gcc >> with lots of warnings can pick up on many such cases. > > Yeah, another common mistake is thinking warnings are just "warnings". > Code so that there are none. >
Agreed - warnings are an indication that you've got something wrong, or at least risky, in your code (or an indication that you've got a poor quality compiler that has silly ideas about warnings!). The more you can find out at compile-time, rather than run-time (or after delivery time), the better. In this case, "-Wall" in gcc includes "-Wparentheses" which warns about "a < b < c", and also something like "if (x = y) { ... }". "-Wall" also includes "-Wunused-value", which is commonly triggered if you write something like "x == y;" instead of "x = y;". Of course, the OP may be using a compiler other than gcc, though gcc is increasingly common - other compilers will typically also have warnings for that sort of basic mistake.
Oltimer wrote:
> > Learning some embedded C using Microchip's C18 Lite. >
This book: http://www.amazon.com/The-Programming-Language-Brian-Kernighan/dp/0131103628 will save you hours of grief.
> > I tried the following and it misbehaved: > > if( 10 < my_variable < 20 ) > { //do this......} > > > > Using the following works: > > if (( x > 10) & ( x < 20)) > { //do this.....} > > > > Is it normal that C cannot handle complexities such as "a < b < c" ?
"<" is a binary logic operator. Binary operators like that in 'C' produce a 1 or 0 result. " 10 < my_variable ..." produces a 1 or 0, which will always be less than 20. This assuming the construct even scans ( I suspect it will ). that "&" should probably be a "&&". "&" means "bitwise and"; "&&" means "logical and". In 'C', "logical" means "over the domain and range of 0/1" with the odd choice that nonzero can be read as 1 - "( 42 && 0 )" reads the same a "(1 && 0)"
> I would have thought a compiler could easily work out what was intended. >
Anything is possible until you know the details. Learn to write little "scope loops" to test your assumptions. This being said, since you're on a Microchip. you can use breakpoints. This is slower and more error prone than printfs, but it'll work. A technique I still sometimes use is to write the code to run against Mingw on a Windows machine or just plain gcc on a Linux to prove it out. The general case is that Microchip targets I run into lack a console serial port, so it's easier to test off target.
> Thanks.
-- Les Cargill
On 20/09/15 19:40, Les Cargill wrote:
> Oltimer wrote: >> >> Learning some embedded C using Microchip's C18 Lite.
I hadn't noticed that the OP was using a PIC18. Of course, if you are interested in learning about C, programming embedded systems, or simply using a half-decent compiler, then pick any microcontroller except a Microchip PIC. PICs (and 8051's) should be banned from any beginners on the grounds that they cause more harm than good. Get a chip with a Cortex M core, or at least an AVR or msp430. Then you can use proper development tools and program in normal C.
> > This book: > > http://www.amazon.com/The-Programming-Language-Brian-Kernighan/dp/0131103628 > > > will save you hours of grief.
It will also cause you hours of grief - because although it is a fairly complete guide to C, it is not the best tutorial out there, it is for a seriously outdated version of C (C11 is the current standard, though there are few practical changes from C99. But C99 is a significantly better programming language than ANSI C for most uses), and it concentrates on C for big systems - not for embedded systems. I don't know what the best choice of tutorial is for learning modern embedded C, but the oldest known C book is not it.

The 2024 Embedded Online Conference