x == (x = y)가 (x = y) == x와 같지 않은 이유는 무엇입니까?
다음 예를 생각해 보겠습니다.
class Quirky {
public static void main(String[] args) {
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
x = 1; // reset
System.out.println((x = y) == x); // true
}
}
이 있는지 x = y
괄호로 둘러싸인 순서에 따라 먼저 계산해야 합니다.
은 왜 평가합니까?false
, 두 에서는 '''를 선택합니다true
(x = y)
.x
자체와 함께(자신에게)3
및 return (반환)true
.
이 질문은 자바 표현식의 서브 표현식의 평가 순서와는 다릅니다.x
여기서 '하위 표현'은 절대 아닙니다.'평가'가 아니라 비교를 위해 로드해야 합니다.이 질문은 Java에 따라 다르며,x == (x = y)
일반적으로 까다로운 인터뷰 질문을 위해 만들어진 매우 비현실적인 구조와는 달리, 실제 프로젝트에서 나왔습니다.'의 사자성어'를 한 줄 요.
int oldX = x;
x = y;
return oldX == y;
이것은 x86 CMPXCHG 명령어보다 훨씬 단순하기 때문에 자바어로 더 짧은 표현을 할 가치가 있습니다.
==
는 2진수 등호 연산자입니다.
이진 연산자의 왼쪽 피연산자는 오른쪽 피연산자의 어떤 부분도 평가되기 전에 완전히 평가되는 것으로 보입니다.
루이스 워서맨의 말처럼 이 표현은 왼쪽에서 오른쪽으로 평가된다.또한 Java는 실제로 "평가"가 무엇을 하는지는 신경 쓰지 않고, 작업할 수 있는 (비휘발성, 최종) 값을 생성하는 데만 신경을 씁니다.
//the example values
x = 1;
y = 3;
첫 출력을 .System.out.println()
다음 작업을 수행합니다.
x == (x = y)
1 == (x = y)
1 == (x = 3) //assign 3 to x, returns 3
1 == 3
false
두 번째 값을 계산합니다.
(x = y) == x
(x = 3) == x //assign 3 to x, returns 3
3 == x
3 == 3
true
인 true에 됩니다.x
★★★★★★★★★★★★★★★★★」y
하고 있기 「」는 「」입니다.a = b
★★★★★★★★★★★★★★★★★」b
의지는 그 순서로 평가되며 정의상 항상 동일하다.
괄호로 둘러싸인 순서에 따라 먼저 계산해야 합니다.
아니요. 괄호가 계산이나 평가 순서에 영향을 미친다는 것은 일반적인 오해입니다.표현식의 일부만 특정 트리로 강제하여 올바른 오퍼랜드를 작업에 적합한 오퍼랜드로 바인딩합니다.
(이 정보를 사용하지 않는 경우, 이 정보는 연산자의 "우선순위"와 연관성으로부터 얻을 수 있습니다.이것은 언어의 구문 트리가 어떻게 정의되어 있는지에 따른 결과입니다.실제로 괄호를 사용할 때도 이와 동일하게 동작합니다.단, 여기서는 우선 순위 규칙에 의존하지 않는다는 것을 알 수 있습니다.
이 작업이 완료되면(즉, 코드를 프로그램으로 해석한 후) 이러한 오퍼랜드를 평가할 필요가 있으며, 이 작업에는 (Andrew가 보여준 바와 같이) 각 동작의 LHS가 Java에서 먼저 평가된다고 기술한 규칙이 있습니다.
C에서는 C++와 같은 하지 않는.&&
★★★★★★★★★★★★★★★★★」||
오퍼랜드의 평가 순서는 일반적으로 지정되지 않으므로 어느 쪽이든 의존해서는 안 됩니다.
교사는 연산자 우선 순위를 "이것이 추가를 먼저 발생시킨다"와 같은 잘못된 문구를 사용하여 설명하는 것을 중단해야 합니다.「 」라고 하는 있다.x * y + z
''는 설명이 x * y
★★★★★★★★★★★★★★★★★」z
에)가 y
★★★★★★★★★★★★★★★★★」z
명령에.명령'은 일절 언급하지 않았다.
Java Language Specification에 변수의 이전 값을 로드하도록 지시하는 항목이 있는지 잘 모르겠습니다.
있어.다음에 사양이 불분명한 경우는, 사양을 읽고 불명확한 점이 있으면 질문해 주세요.
...오른쪽
(x = y)
괄호로 둘러싸인 순서에 따라 먼저 계산해야 합니다.
그 진술은 거짓이다.괄호는 평가 순서를 의미하지 않습니다.Java에서는 괄호에 관계없이 왼쪽에서 오른쪽으로 평가 순서가 지정됩니다.괄호는 평가 순서가 아니라 하위 표현식 경계의 위치를 결정합니다.
첫 번째 식은 false로 평가되고 두 번째 식은 true로 평가되는 이유는 무엇입니까?
의 ==
연산자: 왼쪽을 평가하여 값을 생성하고, 오른쪽을 평가하여 값을 생성하고, 값을 비교합니다. 비교는 식의 값입니다.
즉, 의 의미는expr1 == expr2
is always the same as though you had written temp1 = expr1; temp2 = expr2;
and then evaluated temp1 == temp2
.
The rule for the =
operator with a local variable on the left side is: evaluate the left side to produce a variable, evaluate the right side to produce a value, perform the assignment, the result is the value that was assigned.
So put it together:
x == (x = y)
We have a comparison operator. Evaluate the left side to produce a value -- we get the current value of x
. Evaluate the right side: that's an assignment so we evaluate the left side to produce a variable -- the variable x
-- we evaluate the right side -- the current value of y
-- assign it to x
, and the result is the assigned value. We then compare the original value of x
to the value that was assigned.
You can do (x = y) == x
as an exercise. Again, remember, all the rules for evaluating the left side happen before all the rules of evaluating the right side.
I would have expected (x = y) to be evaluated first, and then it would compare x with itself (3) and return true.
Your expectation is based on a set of incorrect beliefs about the rules of Java. Hopefully you now have correct beliefs and will in the future expect true things.
This question is different from "order of evaluation of subexpressions in a Java expression"
This statement is false. That question is totally germane.
x is definitely not a 'subexpression' here.
This statement is also false. It is a subexpression twice in each example.
It needs to be loaded for the comparison rather than to be 'evaluated'.
I have no idea what this means.
Apparently you still have many false beliefs. My advice is that you read the specification until your false beliefs are replaced by true beliefs.
The question is Java-specific and the expression x == (x = y), unlike far-fetched impractical constructs commonly crafted for tricky interview questions, came from a real project.
The provenance of the expression is not relevant to the question. The rules for such expressions are clearly described in the specification; read it!
It was supposed to be a one-line replacement for the compare-and-replace idiom
그 한 줄 치환으로 인해 코드 판독자인 당신에게 큰 혼란이 생겼기 때문에 잘못된 선택이었다고 생각합니다.코드를 더 간결하게 하지만 이해하기 어렵게 만드는 것은 성공이 아닙니다.그것이 코드를 더 빠르게 만들 것 같지는 않다.
덧붙여서, C#은 비교 치환하는 라이브러리 메서드를 가지고 있으며, 이는 기계 명령에 따라 설정할 수 있다.자바 타입의 시스템에서는 나타낼 수 없기 때문에 자바에는 그러한 메서드가 없다고 생각합니다.
이는 연산자의 우선 순위 및 연산자의 평가 방법과 관련이 있습니다.
괄호 '(')'는 우선순위가 높고 왼쪽에서 오른쪽으로 연관성이 있습니다.평등 '=='은 이 질문의 다음이며 왼쪽에서 오른쪽으로 연관성이 있습니다.과제 '='는 마지막에 오고 오른쪽에서 왼쪽으로 연관성이 있습니다.
스택을 사용하여 식을 평가합니다.표현식은 왼쪽에서 오른쪽으로 평가됩니다.
이제 첫 번째 질문으로 넘어가겠습니다.
int x = 1;
int y = 3;
System.out.println(x == (x = y)); // false
첫 번째 x(1)가 스택에 푸시됩니다.그러면 내부(x = y)가 평가되고 값 x(3)로 스택으로 푸시됩니다.여기서 x(1)는 x(3)와 비교되므로 결과는 false입니다.
x = 1; // reset
System.out.println((x = y) == x); // true
여기서 (x = y)가 평가되고 x 값이 3이 되고 x(3)가 스택으로 푸시됩니다.이제 등식 후에 값이 변경된 x(3)가 스택에 푸시됩니다.이제 식이 평가되고 둘 다 같기 때문에 결과가 참입니다.
그것은 같지 않다.왼쪽은 항상 오른쪽보다 먼저 평가되며, 괄호는 실행 순서를 지정하지 않고 명령어 그룹을 지정합니다.
포함:
x == (x = y)
기본적으로 다음과 같은 작업을 수행합니다.
x == y
그리고 비교 후 x의 값은 y가 됩니다.
사용 중:
(x = y) == x
기본적으로 다음과 같은 작업을 수행합니다.
x == x
x가 y의 값을 가져간 후.그리고 그것은 항상 사실로 돌아올 것이다.
첫 번째 검정에서는 1 == 3을 수행합니다.
두 번째 검정에서는 3 == 3이 검사됩니다.
(x = y)가 값을 할당하고 해당 값이 테스트됩니다.전자의 예에서는 x = 1 먼저 x가 3으로 할당됩니다.1 == 3 인가요?
후자의 경우, x는 3이 할당되어 있고, 확실히 아직 3입니다.3 == 3 인가요?
다른 간단한 예를 생각해 봅시다.
int x = 1;
System.out.println(x == ++x); // false
x = 1; // reset
System.out.println(++x == x); // true
여기서, 사전 증가 연산자는++x
비교하기 전에 적용해야 합니다.(x = y)
비교 전에 계산해야 합니다.
그러나 표현 평가는 여전히 왼쪽 → 대 오른쪽 →로 이루어지므로 첫 번째 비교는 실제로1 == 2
두 번째는2 == 2
.
이 예에서도 같은 일이 발생합니다.
표현식은 왼쪽에서 오른쪽으로 평가됩니다.이 경우:
int x = 1;
int y = 3;
x == (x = y)) // false
x == t
- left x = 1
- let t = (x = y) => x = 3
- x == (x = y)
x == t
1 == 3 //false
(x = y) == x); // true
t == x
- left (x = y) => x = 3
t = 3
- (x = y) == x
- t == x
- 3 == 3 //true
기본적으로 첫 번째 문 x는 값이 1이므로 Java는 1 ==을 동일하지 않을 새로운 x 변수와 비교합니다.
두 번째 예에서는 x=y라고 했는데, 이는 x의 값이 바뀌었다는 것을 의미하기 때문에 다시 불러올 때 같은 값이 되므로 x==x가 참인 이유를 알 수 있습니다.
==는 비교 동등 연산자로 왼쪽에서 오른쪽으로 작동합니다.
x == (x = y);
여기서 이전 할당 값 x를 새 할당 값 x, (1==3)/false와 비교합니다.
(x = y) == x;
반면, 여기서 x의 새 할당 값은 비교 직전에 할당된 x의 새 보유 값과 비교된다. (3==3)//true
자, 생각해 보세요
System.out.println((8 + (5 * 6)) * 9);
System.out.println(8 + (5 * 6) * 9);
System.out.println((8 + 5) * 6 * 9);
System.out.println((8 + (5) * 6) * 9);
System.out.println(8 + 5 * 6 * 9);
출력:
342
278
702
342
278
따라서 괄호는 비교식이 아닌 산술식에서만 중요한 역할을 합니다.
여기서 중요한 것은 두 연산자의 산술 연산자/관계 연산자 우선 순위입니다.=
대==
지배적인 것은==
(Relational Operators가 우세합니다)=
할당 연산자우선 순위에도 불구하고 평가 순서는 LTR(LEFT TO RIGHT) 우선 순위입니다.따라서 어떠한 제약조건에 관계없이 평가는 LTR입니다.
왼쪽의 두 번째 비교는 y를 x(왼쪽)에 할당한 다음 3 == 3을 비교한 후 할당하는 것입니다.첫 번째 예제에서는 x = 1을 새 할당 x = 3과 비교합니다.x의 왼쪽에서 오른쪽으로 항상 현재 상태를 읽는 글이 있는 것 같습니다.
Java 컴파일러를 작성하거나 프로그램을 테스트하여 Java 컴파일러가 올바르게 동작하고 있는지 확인하려면 이 질문을 하는 것이 좋습니다.Java 에서는 이 두 식을 통해 표시된 결과가 생성되어야 합니다.예를 들어 C++에서는 그럴 필요가 없습니다.따라서 누군가가 Java 컴파일러에서 C++ 컴파일러의 일부를 재사용한 경우 이론적으로 컴파일러가 정상적으로 동작하지 않는 것을 알 수 있습니다.
소프트웨어 개발자로서 읽기 쉽고, 이해하기 쉽고, 유지보수가 용이한 코드를 작성하는 것은 두 버전의 코드 모두 끔찍하다고 여겨질 것입니다.코드가 무엇을 하는지 이해하려면 Java 언어가 어떻게 정의되는지 정확히 알아야 합니다.자바 코드와 C++ 코드를 모두 쓰는 사람은 코드를 보고 전율할 것이다.한 줄의 코드가 왜 이 기능을 하는지 물어봐야 할 경우 이 코드를 피해야 합니다.(당신의 "왜" 질문에 올바르게 답한 사람도 그러한 코드 표시를 피하기를 바라고 있습니다).
언급URL : https://stackoverflow.com/questions/53749841/why-is-x-x-y-not-the-same-as-x-y-x
'sourcecode' 카테고리의 다른 글
함수에서 char*를 반환하는 것과 char[]를 반환하는 것의 차이점은 무엇입니까? (0) | 2022.08.31 |
---|---|
VueX를 통한 데이터 액세스 (0) | 2022.08.31 |
플레인 파일을 실행 파일에 링크할 수 있습니까? (0) | 2022.08.31 |
Linux에서 C에 디렉토리를 반복적으로 나열하는 방법 (0) | 2022.08.31 |
"메인 클래스를 찾을 수 없거나 로드할 수 없습니다"는 무슨 의미입니까? (0) | 2022.08.31 |