developer tip

덧셈 할당 + = 식의 동작

copycodes 2020. 12. 12. 11:27
반응형

덧셈 할당 + = 식의 동작


최근에 할당 연산자 체인 이해라는 질문을 보았습니다 .

이 질문에 대답하는 동안 나는 또한 대입 연산자의 동작의 내 자신의 이해 의심하기 시작 +=또는 기타를 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. 이해해야 할 요점은 덧셈이 왼쪽에서 오른쪽으로 평가 된다는 것입니다. 즉, ain a + xx.

그래서 무엇을하는지 알아 봅시다 b = (a += (a += a)). 먼저 a += xmeans 규칙을 사용한 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 = 4b = 6. 이 모두를 인쇄하여 확인할 수 있습니다 ab자바 / 자바 스크립트 (모두 여기에 같은 동작을)에.


이러한 표현식을 구문 분석 트리로 생각하는 것도 도움이 될 수 있습니다. 평가할 때 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

반응형