2

Stéphane Chazelas gave two examples in The value of a variable is evaluated as an arithmetic expression when it is referenced, or assigned

$ a=1+1; echo "$((a * 3)) $(($a * 3))"
6 4

$ a=a=b++ b=1 bash -c 'echo "$((++a)) $b"'
2 2

I understand there is indirect expansion for variable expansion in arithmetic expressions. But I can't figure out

  • how do a and $a in the first example result in such a difference? My confusion comes from that in arithmetic expressions, parameter expansion of a variable doesn't need ${}, just write the variable directly.

  • how is the arithmetic expression in the second example evaluated?

Thanks.

4
  • Because 1+1*3 equals 4 by order of operations. For the second one, I have no idea.
    – Wildcard
    Jul 27 '17 at 22:25
  • For the first example, my confusion is that In arithmetic expressions, parameter expansion of a variable doesn't need ${}, just write the variable directly.
    – Tim
    Jul 27 '17 at 22:26
  • 1
    In one case, the value of a is parsed before it's placed into the context of ((a * 3)), yielding ((2 * 3)), which evaluates to six. In the other, it is dropped in unparsed, so it is dropped in as (( 1+1 * 3 )) at which mathematical order of operations takes hold.
    – DopeGhoti
    Jul 27 '17 at 22:27
  • Both examples are ilegal and a shell that does not flag them as bad is questionable. Neither 1+1 nor b++ are numbers, but they have to be numbers if they are referenced via a construct like $((var)).
    – schily
    May 28 '20 at 6:40
4

Parameter expansion isn’t the same as arithmetic evaluation.

In an arithmetic expression, a text string such as a is interpreted as a variable name, and the value of that variable is processed as an arithmetic expression itself, and the result used in the containing arithmetic expression. Thus

$((a * 3))

causes the value of the variable a, 1+1, to be evaluated as an arithmetic expression, yielding 2, and the whole expression becomes $((2 * 3)), i.e. 6.

In the same context, $a is replaced with the value of a as-is, in an earlier phase (this is parameter expansion); so

$(($a * 3))

becomes $((1+1 * 3)), which is 4 following the usual precedence rules.

In the second example, $((++a)) is processed before $b (processing takes place from left to right). The arithmetic expression causes a to be evaluated as an arithmetic expression itself, as above; the value of a is a=b++, which when evaluated, assigns the value of b (itself evaluated as an arithmetic expression) to a, then increments b. Thus after evaluating a, b is 2 and a is 1. Evaluating $((++a)) increments a and returns its value, which is now 2. $b is just replaced with the value of b, 2 as well. After the quoted argument to echo is processed, the echo is run with 2 2 as its sole argument, producing the output you saw.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.