덧셈 할당 + = 식의 동작
최근에 할당 연산자 체인 이해라는 질문을 보았습니다 .
이 질문에 대답하는 동안 나는 또한 대입 연산자의 동작의 내 자신의 이해 의심하기 시작 +=
또는 기타를 operator=
( &=
, *=
, /=
, 등).
내 질문은 언제 a
아래 표현식 의 변수 가 제자리에서 업데이트되어 평가 중에 변경된 값이 표현식의 다른 위치에 반영되도록하는 것이며 그 뒤에있는 논리는 무엇입니까? 다음 두 가지 표현을 살펴보십시오.
식 1
a = 1
b = (a += (a += a))
//b = 3 is the result, but if a were updated in place then it should've been 4
식 2
a = 1
b = (a += a) + (a += a)
//b = 6 is the result, but if a is not updated in place then it should've been 4
첫 번째 표현식에서 가장 안쪽 표현식 (a += a)
을 평가하면의 값을 업데이트하지 않는 것처럼 보이 a
므로 결과가 3
대신으로 나옵니다 4
.
그러나 두 번째 표현식에서는의 값 a
이 업데이트되므로 결과는 6입니다.
a
의 가치가 표현의 다른 위치에 반영 될 것이라고 언제 가정해야하며, 언제 반영하지 않아야합니까?
그것이 a += x
정말로 의미 한다는 것을 기억하십시오 a = a + x
. 이해해야 할 요점은 덧셈이 왼쪽에서 오른쪽으로 평가 된다는 것입니다. 즉, a
in a + x
이 x
.
그래서 무엇을하는지 알아 봅시다 b = (a += (a += a))
. 먼저 a += x
means 규칙을 사용한 a = a + x
다음 올바른 순서로 표현식을 신중하게 평가하기 시작합니다.
b = (a = a + (a = a + a))
a += x
의미 때문에a = a + x
b = (a = 1 + (a = a + a))
때문에이a
현재1
.a
오른쪽 용어 이전에 왼쪽 용어 를 평가한다는 것을 기억하십시오.(a = a + a)
b = (a = 1 + (a = 1 + a))
왜냐하면a
여전히1
b = (a = 1 + (a = 1 + 1))
왜냐하면a
여전히1
b = (a = 1 + (a = 2))
때문에1 + 1
입니다2
b = (a = 1 + 2)
때문에a
지금2
b = (a = 3)
때문에1 + 2
입니다3
b = 3
때문에a
지금3
이 잎 우리와 함께 a = 3
하고 b = 3
위의 추론있다.
다른 표현식으로 시도해 봅시다 b = (a += a) + (a += a)
.
b = (a = a + a) + (a = a + a)
b = (a = 1 + 1) + (a = a + a)
, 오른쪽 용어 앞에 왼쪽 용어를 평가한다는 것을 기억하십시오.b = (a = 2) + (a = a + a)
b = 2 + (a = a + a)
그리고a
지금 올바른 용어를 평가 2. 시작이다b = 2 + (a = 2 + 2)
b = 2 + (a = 4)
b = 2 + 4
그리고a
지금4
b = 6
이로 인해 a = 4
및 b = 6
. 이 모두를 인쇄하여 확인할 수 있습니다 a
및 b
자바 / 자바 스크립트 (모두 여기에 같은 동작을)에.
이러한 표현식을 구문 분석 트리로 생각하는 것도 도움이 될 수 있습니다. 평가할 때 a + (b + c)
LHS a
는 RHS보다 먼저 평가 (b + c)
됩니다. 이것은 트리 구조로 인코딩됩니다.
+
/ \
a +
/ \
b c
더 이상 괄호가 없습니다. 연산 순서는 트리 구조로 인코딩됩니다. 트리에서 노드를 평가할 때 노드의 자식을 고정 된 순서로 처리합니다 (예 :에서 왼쪽에서 오른쪽으로 +
). 예를 들어 루트 노드를 처리 할 때 오른쪽 하위 트리가 괄호로 묶여 있는지 여부에 관계없이 오른쪽 하위 +
트리 a
이전에 왼쪽 하위 트리 를 평가합니다 (b + c)
(괄호가 구문 분석 트리에 존재하지 않기 때문).
이 때문에 Java / JavaScript는 산술에 대해 학습했을 수있는 규칙과 달리 항상 "가장 중첩 된 괄호"를 먼저 평가 하지는 않습니다 .
Java 언어 사양을 참조하십시오 .
15.7. 평가 순서
Java 프로그래밍 언어는 연산자의 피연산자가 특정 평가 순서 , 즉 왼쪽에서 오른쪽 으로 평가되는 것처럼 보이도록 보장합니다 .
...15.7.1. 왼손 피연산자 먼저 평가
이항 연산자의 왼쪽 피연산자는 오른쪽 피연산자의 일부가 평가되기 전에 완전히 평가 된 것처럼 보입니다.
연산자가 복합 할당 연산자 (§15.26.2) 인 경우 왼쪽 피연산자의 평가에는 왼쪽 피연산자가 나타내는 변수를 기억하는 것과 묵시적 이진 연산에 사용하기 위해 해당 변수의 값을 가져와 저장하는 작업이 모두 포함됩니다. .
귀하의 질문과 유사한 더 많은 예는 다음과 같은 JLS의 링크 부분에서 찾을 수 있습니다.
예 15.7.1-1. 왼손 피연산자가 먼저 평가됨
다음 프로그램에서 * 연산자에는 변수에 대한 할당이 포함 된 왼쪽 피연산자와 동일한 변수에 대한 참조가 포함 된 오른쪽 피연산자가 있습니다. 참조에 의해 생성 된 값은 할당이 먼저 발생했다는 사실을 반영합니다.
class Test1 { public static void main(String[] args) { int i = 2; int j = (i=3) * i; System.out.println(j); } }
이 프로그램은 출력을 생성합니다.
9
* 연산자의 평가에서 9 대신 6을 생성하는 것은 허용되지 않습니다.
다음은주의해야 할 규칙입니다.
- 연산자 우선 순위
- 변수 할당
표현 평가
식 1
a = 1 b = (a += (a += a)) b = (1 += (a += a)) // a = 1 b = (1 += (1 += a)) // a = 1 b = (1 += (1 += 1)) // a = 1 b = (1 += (2)) // a = 2 (here assignment is -> a = 1 + 1) b = (3) // a = 3 (here assignment is -> a = 1 + 2)
식 2
a = 1 b = (a += a) + (a += a) b = (1 += a) + (a += a) // a = 1 b = (1 += 1) + (a += a) // a = 1 b = (2) + (a += a) // a = 2 (here assignment is -> a = 1 + 1) b = (2) + (2 += a) // a = 2 (here here a = 2) b = (2) + (2 += 2) // a = 2 b = (2) + (4) // a = 4 (here assignment is -> a = 2 + 2) b = 6 // a = 4
식 3
a = 1 b = a += a += a += a += a b = 1 += 1 += 1 += 1 += 1 // a = 1 b = 1 += 1 += 1 += 2 // a = 2 (here assignment is -> a = 1 + 1) b = 1 += 1 += 3 // a = 3 (here assignment is -> a = 1 + 2) b = 1 += 4 // a = 4 (here assignment is -> a = 1 + 3) b = 5 // a = 5 (here assignment is -> a = 1 + 4)
작업 순서의 변형을 사용합니다.
작업 순서에 대한 알림이 필요한 경우 :
PEMDAS :
P = 괄호
E = 지수
MD = 곱셈 / 나눗셈
AS = 더하기 / 빼기
나머지는 왼쪽에서 오른쪽으로.
This variation just is read left to right, but if you see a parenthesis do everything inside it, and replace it with a constant then move on.
First ex:
var b = (a+=(a+=a))
var b = (1+=(1+=1))
var b = (1+=2)
var b = 3
Second ex:
var b = (a+=a)+(a+=a)
var b = (1+=1)+(a+=a)
var b = 2 + (2+=2)
var b = 2 + 4
var b = 6
var a = 1
var b = (a += (a += a))
console.log(b);
a = 1
b = (a += a) + (a += a)
console.log(b);
a = 1
b = a += a += a;
console.log(b);
The last one b = a += a += a
since there are no parenthesis, it automatically becomes b = 1 += 1 += 1
which is b = 3
참고URL : https://stackoverflow.com/questions/50869790/addition-assignment-behavior-in-expression
'developer tip' 카테고리의 다른 글
BeginProcessRequest ()에서 어떤 일이 발생합니까? (0) | 2020.12.12 |
---|---|
Typescript에서 따옴표를 사용하는 표준은 무엇입니까? (0) | 2020.12.12 |
C ++에서 함수를 호출 할 때 얼마나 많은 오버 헤드가 있습니까? (0) | 2020.12.12 |
Android- android.net.Uri 객체를 java.net.URI 객체로 어떻게 변환 할 수 있습니까? (0) | 2020.12.12 |
컨텍스트가없는 프로그래밍 언어는 무엇입니까? (0) | 2020.12.12 |