할당과 평등 검사를 결합한 if 문이 왜 true를 반환합니까?


216

나는 초보자 실수를 생각하고 있었고 if성명서 에서 실수로 끝났습니다 . 코드를 조금 확장했습니다.

int i = 0;
if (i = 1 && i == 0) {
    std::cout << i;
}

나는이 본 if문 반환 사실, 그것은 couti1. 경우 i할당 1한 이유는 if 문에서 i == 0수익을 true?


83
여러분, 이것은 오타 질문이 아닙니다. OP는로 i설정되어 있기 때문에 if 코드가이 코드로 입력 된 이유를 알고 싶어 합니다 1.
NathanOliver

24
아니면 결과를 할당 1 && i == 0합니까?
JVApen

4
초보자를위한 제안 : "고급"언어 구성을 사용해서는 안됩니다. 변수를 별도로 할당하십시오. 그것은 또한 시퀀스 포인트에 가능한 문제를 피할 것입니다. 실제 코드에서 이러한 종류의 코드는 일반적으로 나쁘게 보입니다.
user202729

1
이것은 인터뷰 문제로 끝날 것입니다
RAZ_Muh_Taz

답변:


391

이것은 연산자 우선 순위 와 관련이 있습니다 .

if (i = 1 && i == 0)

아니다

if ((i = 1) && (i == 0))

모두 있기 때문에 &&그리고 ==보다 높은 우선 순위를 가지고 =. 그것이 실제로 작동하는 것은

if (i = (1 && (i == 0)))

이는 할당의 결과 1 && (i == 0)로이 i. 그래서, 만약 i에 시작 0후이 i == 0있다 true, 그래서 1 && true이다 true(또는 1), 다음 i으로 설정됩니다 1. 그런 다음 1true이므로 if 블록을 입력하고에 할당 한 값을 인쇄하십시오 i.


2
@ JörgWMittag 정말 멋지다. 괄호를 사용하도록 강요합니다.
NathanOliver

기본적으로 i = !i; if (i)올바르게 작성
Cacahuete Frito

@NathanOliver : Fortress는 매우 멋진 언어로 많은 것들을 올바르게했습니다. (리드 디자이너 인 Guy L. Steele은 놀라웠습니다.) 불행히도 DARPA 자금 지원을 위해 최종 선정되지 않았으며, 이후 Oracle에 의해 모방되었습니다.
Jörg W Mittag

6
당연히, 컴파일러로부터 경고를 요청하면 그 오류를 감지했을 것입니다.
Deduplicator

4
int와 boolean을 가정하지 않는 언어도 이것을 선택할 것입니다.
rghome

16

코드가 실제로 다음과 같다고 가정합니다.

#include <iostream>
using namespace std;

int main()  {
    int i = 0;
    if (i = 1 && i == 0) {
        cout << i;
    }
}

그런 다음

if (i = 1 && i == 0) {

로 평가

 if (i = (1 && i == 0)) {

i으로 설정되어 있습니다 1.


39
추가 코드가 정말로 필요 했습니까? 달리 실행되지 않기 때문에 이것이 사실 일 것입니다.
Modelmat

13
불필요한 추가 코드뿐만 아니라 답은 연산자 우선 순위를 명확하게 설명하지 못합니다.
Francisco Zarabozo

34
우리가 nitpick 열차에있어 이후 ... 내가 볼 using namespace std!
Mateen Ulhaq

8
추가 코드가 있지만 여전히 잘못된 코드는 아닙니다. 그리고 대답은 여전히 ​​옳습니다. 물론 연산자 우선 순위를 설명하지는 않습니다. 그러나 누군가는 완전히 투표하지 않고 추가하도록 제안 할 수 있습니다!
B Charles H

14
와우, -4는 가혹하지만, 이것이 최적의 방법은 아니지만 질문에 올바르게 대답한다는 것을 고려하십시오. 다른 답변만큼 연산자 우선 순위를 확장하지는 않지만 코드의 맥락에서 연산자 우선 순위에 대해 충분히 말하여 =이전에 생각한 사람 &&이 문제를 볼 수 있습니다. 또한 그렇습니다. 확장이 외래이지만 그다지 중요하지 않다고 생각합니다. 나는 그러한 사소한 차이로 인해 사람들이 151에서 -4로 투표한다고 믿을 수 없습니다.
JoL

-4

오른쪽에서 왼쪽으로 규칙을 구문 분석하는 것과 관련이 있습니다. 예를 들어 y = x + 5입니다.
모든 하위 표현의 중요성이 중요합니다. 똑같이 중요한 두 가지 표현이 오른쪽에서 왼쪽으로 평가됩니다. && 표현식 측면이 먼저 수행 된 후 LHS가 수행됩니다.

이해가 되네요


1
연관성 ( "오른쪽에서 왼쪽으로의 규칙")은 이와 관련이 없습니다. 우선 순위 ( "중요도")에 관한 것이며 사용 된 연산자의 우선 순위는 동일 하지 않습니다 .
궤도에서 가벼움 레이스

-4

실제 답변은 다음과 같습니다.

  1. 컴파일러는 "i == 0"에 우선 순위 를 부여 하며, 이는 true로 평가됩니다.
  2. 그런 다음 i = 1을 TRUE 또는 FALSE로 평가하고 컴파일 된 할당 연산자가 실패하지 않기 때문에 (그렇지 않으면 컴파일되지 않음) true로 평가됩니다.
  3. 두 명령문 모두 true로 평가되고 TRUE && TRUE는 TRUE로 평가되므로 if 문은 TRUE로 평가됩니다.

증거로, 입력 한 코드에 대한 컴파일러의 asm 출력을 살펴보십시오 (모든 주석은 내 자신의 것입니다).

mov     dword ptr [rbp - 8], 0    ; i = 0;
cmp     dword ptr [rbp - 8], 0    ; i == 0?
sete    al                        ; TRUE (=1)
mov     cl, al
and     cl, 1                     ; = operator always TRUE
movzx   edx, cl
mov     dword ptr [rbp - 8], edx  ; set i=TRUE;
test    al, 1                     ; al never changed,
                                  ; so final ans is TRUE

위의 asm 출력은 CLANG에서 가져온 것이지만 내가 본 다른 모든 컴파일러는 비슷한 출력을 냈습니다. 이는 해당 사이트의 모든 컴파일러에 대해 순수한 C 또는 C ++ 컴파일러이든 컴파일러 모드를 변경하는 데 대한 실용주의가없는 것입니다 (기본적으로 C ++ 컴파일러의 경우 C ++ 임)

컴파일러는 실제로 i = 1을 설정하지 않았지만 i = TRUE (정수 값이 아닌 32 비트를 의미 함)입니다. 이는 && 연산자가 명령문이 TRUE인지 FALSE인지 평가 한 후 해당 결과에 따라 결과를 설정하기 때문입니다. 증거로 i = 1을 i = 2로 변경하면 아무것도 변하지 않을 것이라는 것을 스스로 확인할 수 있습니다. 컴파일러 탐색기 에서 온라인 컴파일러를 사용하여 직접 확인하십시오


1
1)이 질문에 C ++ 태그가 지정되면 문서가 C 연산자 우선 순위에 연결됩니다. 서로 다른 두 언어 2a) i = 1할당 (등가 아님) 연산자; 2b) if (i = 0)C와 C ++에서 모두 거짓 상태로 평가 될 것이라고 확신 할 수 있으므로 "실패하지 않는다"고 진정한 wrt로 평가되는지 여부는 다소 오해의 소지가 있습니다.
TrebledJ

1
and cl, 1 ; = operator always TRUE<< 내가 틀렸다면 정정하되, 여기서 할당이 보이지 않습니다. 1 &&표현식 의 일부를 나타냅니다 . 따라서이 답변은 기본적으로로 평가됩니다 false.
syck 2016 년

"이 질문에 C ++ 태그가 지정되면 문서가 C 연산자 우선 순위에 연결됩니다. 두 가지 다른 언어"-C와 C ++ 연산자 우선 순위를 비교할 때 두 문서의 차이점은 무엇입니까? C ++가 C의 직접적인 파생물 (또는 C ++이 C ++ 언어의 하위 집합이므로 C ++이 C ++ 언어의 하위 집합이므로) 은이 주제와 관련하여 동일한 우선 순위를 갖습니다. 우선 순위를 포함한 공통점). 어쨌든 혼란스러운 경우 내 게시물을 수정하겠습니다.
ar18

"내가 틀렸다면 정정하되 여기에 과제가없는 경우"-그러면 바로 정정하겠습니다! 1은 즉각적인 값이며 테스트 또는 계산 결과가 아닙니다. 이를 "추정 된 TRUE"값이라고합니다. 수행되는 유일한 테스트는 i == 0 문, 즉 "cmp dword ptr [rbp-8], 0"입니다. "movzx edx, 1"이라고 말한 경우에만 정확합니다. 내 앞의 모든 게시물에 따르면 두 가지 비교가 있어야하지만 실제로는 하나만 있으며 모든 주요 컴파일러의 asm 출력은 해당 게시물이 완전히 잘못되었음을 증명합니다.
ar18

2
우선 순위가 잘못되었을뿐만 아니라 (올바른 구문 분석에 대해서는 NathanOliver의 답변 참조) 할당 연산자가 항상 TRUE로 사라진다는 잘못된 주장을합니다. 시도하십시오 if ( i = 0 ) { print something }. 또한 당신의 대답은 모순됩니다; 처음에는 i=1이전에 평가 되었다고 말한 &&다음 연산자 i의 결과로 설정 되었다고 말합니다 &&.
MM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.