Bash arithmetic issue

I found the following issue by simply increasing a variable. The

((A++))

expression returns an error, the other expressions both return 0. Does anyone know why?

script.sh:

    #! /bin/bash

    A=0
    B=0
    C=0

    ((A++))   ; echo "${?}"
    ((B=B+1)) ; echo "${?}"
    ((C+=1))  ; echo "${?}"

# ./script.sh
1
0
0

This is specified and expected behaviour. man bash :

A++ is post-increment, i.e. A is evaluated (to zero, thus return status 1) and then incremented. ++A will return the expected 0 .

3 Likes

You are right - thank you very much! I couldn't find the info in my bash man page yet. Nevertheless, this is a stupid behaviour of the bash.

Why stupid? It't explainable and logic.

Hm, I found the point in the man page now. It was imho a bad decision to change the behaviour of the (()) expression. Why should a successful expression return a non zero exit code?

And still it is an inconsitent behaviour:

((A=0))

returns 1

 declare -i B ; B=B+0 

returns 0

You are aware what $? means, yes? It's a return code. It is not a mathematical result, but it is the result of the expression.

The result of the expression (( X = 0 )) is zero, which considered as a boolean means false, which as a return code means failure, so $? becomes 1.

The result of (( X = 1 )) is nonzero, which considered as a boolean means true, which as a return code means success, so $? becomes 0.

It does this because this is how mathematical functions work in most languages, which is what (( )) is for. If you don't want to do that, there's the old fashioned way.

Which is not what you showed, anyway:

$ B=B+0
$ echo B
B+0

$

Shell variables do not work that way.

I don't want to struggle, but IMO there are at least two ways to make the same arithmetic expression:

((B=0))

returning 1

and

declare -i B ; B=B+0

returning 0

and I only wanted to point out that this is an inconsistent behaviour. But, ok, we have two different operators here: (()) and the 'declare' one.

The entire reason (( )) exists is it behaves differently. (( )) is a modern C-style expression where you can mix assignments and comparisons, with a return code like you'd expect of such expressions. It's the modern way to do math and comparison in Bourne shell.

If this is inconsistent with the math syntax of plain Bourne circa 1977, well, good. There's a reason it's considered depreciated for modern shells.

You are right. It's the same behaviour as in C (and I like C). So, thank you for the discussion. You changed my mind.