1

I suspect this is intentional (rather than just a bug). If so, please direct me to the relevant documentation for a justification.

~$ i=0; ((i++)) && echo true || echo false
false
~$ i=1; ((i++)) && echo true || echo false
true

The only difference between the two lines is i=0 vs i=1.

3
  • 3
    what behaviour did you expect then, and why?
    – ilkkachu
    Commented Mar 8, 2020 at 18:03
  • @ilkkachu I am pointing out that there are situations in which conflating a value that happens to be 0 with an error code, though there's nothing particularly dumb about this design decision, can be misleading. Your implied argument and explanation, that Bash had no choice, is valid and, technically, the preferred (most correct) answer to my question (which required a justification).
    – glarry
    Commented Mar 8, 2020 at 18:20
  • 1
    nah, I was mostly wondering if it was about how the postfix incrementation works, or about the return code of (( )). I think the "why" for the return code behaviour is so that stuff like if (( a == 2 )) works.
    – ilkkachu
    Commented Mar 8, 2020 at 20:34

2 Answers 2

8

This is because i++ does post-increment, as described in man bash. This means that the value of the expression is the original value of i, not the incremented value.

ARITHMETIC EVALUATION
       The  shell  allows  arithmetic  expressions  to  be  evaluated, under certain circumstances (see the let and
       declare builtin commands and Arithmetic Expansion).  Evaluation is done  in  fixed-width  integers  with  no
       check for overflow, though division by 0 is trapped and flagged as an error.  The operators and their prece-
       dence, associativity, and values are the same as in the C language.  The  following  list  of  operators  is
       grouped into levels of equal-precedence operators.  The levels are listed in order of decreasing precedence.

       id++ id--
              variable post-increment and post-decrement

So that:

i=0; ((i++)) && echo true || echo false

acts like:

i=0; ((0)) && echo true || echo false

except that i is incremented too; and that:

i=1; ((i++)) && echo true || echo false

acts like:

i=1; ((1)) && echo true || echo false

except that i is incremented too.

The return value of the (( )) construct is truthy (0) if the value is nonzero, and vice versa.

You can also test how does post-increment operator work:

$ i=0
$ echo $((i++))
0
$ echo $i
1

And pre-increment for comparison:

$ i=0
$ echo $((++i))
1
$ echo $i
1
0
3
]# i=0; ((i++)) && echo true || echo false
false

]# i=0; ((++i)) && echo true || echo false
true

The 'return' value of an ((expression)) depends on pre- or postfix. And then the logic is this:

     ((expression))

     The expression is evaluated according to the rules described be low under ARITHMETIC EVALUATION.

     If the value of the expression is non-zero,
     the return status is 0; 

     otherwise the return status is 1.

This means it is turned around to be normal, not like a return value.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .