문제

이 코드가 왜 14 인쇄를 인쇄하는지 설명 할 수 있습니까? 나는 방금 다른 학생의 질문을 받았으며 그것을 알아낼 수 없었습니다.

int i = 5;
i = ++i + ++i;
cout<<i;
도움이 되었습니까?

해결책

부작용 순서는 C ++에서 정의되지 않았습니다. 또한 단일 표현식에서 변수를 두 번 수정하는 것은 정의 된 동작이 없습니다 ( C ++ 표준, §5.0.4, 물리적 Page 87 / Logical Page 73).

해결책 : 복잡한 표현식에서 부작용을 사용하지 말고 간단한 표현에서 하나 이상을 사용하지 마십시오. 그리고 컴파일러가 당신에게 줄 수있는 모든 경고를 가능하게하는 것은 아프지 않습니다. -Wall(GCC) 또는 /Wall /W4(Visual C ++) 명령 줄에 대한 피팅 경고를 제공합니다.

test-so-side-effects.c: In function 'main':
test-so-side-effects.c:5: warning: operation on 'i' may be undefined
test-so-side-effects.c:5: warning: operation on 'i' may be undefined

분명히 코드는 다음과 같습니다.

i = i + 1;
i = i + 1;
i = i + i;

다른 팁

이는 정의되지 않은 동작이며 결과는 사용하는 컴파일러에 따라 다릅니다. 예를 들어, C ++ FAQ 라이트.

답/의견 중 일부에는 '정의되지 않은 행동'의 의미와 그것이 프로그램을 유효하지 않은지에 대한 토론이있었습니다. 그래서 저는 표준이 어떤 메모로 말하는 것을 정확하게 자세히 설명하는이 긴 대답을 게시하고 있습니다. 너무 지루하지 않기를 바랍니다 ...

표준의 인용 된 비트는 현재 C ++ 표준 (ISO/IEC 14882 : 2003)에서 비롯됩니다. C 표준에는 비슷한 문구가 있습니다.

C ++ 표준에 따르면, 일련의 시퀀스 지점 내에서 값을 두 번 이상 수정하면 정의되지 않은 동작이 발생합니다 (섹션 5 단락 4).

언급 된 경우, 개별 연산자의 피연산자 평가 순서 및 개별 표현의 하위 표현 및 부작용이 발생하는 순서는 지정되지 않습니다. 표현의 평가에 의해 최대 한 번. 또한, 저장 될 값을 결정하기 위해서만 이전 값에 액세스해야합니다. 이 단락의 요구 사항은 완전한 표현의 하위 표현의 각 허용 순서에 대해 충족되어야한다. 그렇지 않으면 동작이 정의되지 않습니다. [예시:

i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented

- 엔드 예

두 번째 예는 "에 유의하십시오."i = 7, i++, i++;"쉼표 연산자가 시퀀스 지점이므로 정의됩니다.

C ++ 표준이 '정의되지 않은 동작'이라는 의미는 다음과 같습니다.

1.3.12 정의되지 않은 행동 [defns.undefined

이 국제 표준이 요구 사항을 부과하는 잘못된 프로그램 구성 또는 잘못된 데이터를 사용하면 발생할 수있는 행동과 같은 행동. 이 국제 표준이 행동의 명시 적 정의에 대한 설명을 생략 할 때 정의되지 않은 행동도 예상 될 수 있습니다. [참고 : 허용되지 않는 행동은 예측할 수없는 결과로 상황을 완전히 무시하고, 환경의 문서화 된 방식으로 문서화 된 방식으로 번역 또는 프로그램 실행 중에 행동에 이르기까지 (진단 메시지의 발행 유무에 관계없이) 번역 또는 실행에 이르기까지 다양합니다. 진단 메시지 발급으로). 많은 잘못된 프로그램 구성은 정의되지 않은 행동을 유발하지 않습니다. 진단을 받아야합니다. ]

다시 말해, 컴파일러는

  1. 오류 메시지를 뱉어 내고
  2. 정의 및 문서화 된 구현,
  3. 완전히 예측할 수없는 결과가 있습니다

두 번째 항목은 대부분의 컴파일러가 가지고있는 언어 확장을 다루지 만 물론 표준에는 정의되지 않습니다.

따라서 정의되지 않은 행동을 나타내는 것을 엄격히 말하는 것은 '불법'이 아니지만 '정의되지 않은 행동'을 나타내는 C/C ++ 프로그램에 무언가가있을 때마다 내 경험상 (확장이 아닌 한). 버그라고 생각합니다. 나는 그러한 구조물을 불법으로 부르는 것이 혼란 스럽거나 오도하거나 잘못 인도되지 않는다고 생각합니다.

또한, 컴파일러가 값 14에 도달하기 위해 무엇을하고 있는지 설명하려고 노력하는 것은 포인트를 놓치므로 특히 도움이되지 않는다고 생각합니다. 컴파일러는 거의 모든 일을 할 수 있습니다. 실제로, 컴파일러는 다른 최적화 옵션을 사용하여 실행될 때 다른 결과에 도달 할 수 있습니다 (또는 충돌하는 코드를 생성 할 수도 있습니다.

추가 참조 또는 권위에 대한 호소를 원하는 사람들을 위해 다음은 다음과 같습니다.

Steve Summit 's (Comp.Lang.c의 자주 묻는 질문 관리자) 1995 년 부터이 주제에 대한 긴 대답 :

Bjarne Stroustrup이 그 문제에 대해 말한 내용은 다음과 같습니다.


각주: C ++ 표준은 '불법'이라는 단어를 정확히 한 번 사용합니다. static 또는 extern 유형 선언과 함께.

간단합니다 ... 컴파일러가 평가 중입니다 둘 다 중간 결과를 캐싱하지 않고 합계를 수행하기 전에 증가합니다. 이것은 당신이 i를 두 번 추가 할 때, 이제 값은 7의 값을 의미합니다.

당신이한다면

int j=++i; 
int k=++i;

i = j+k;

예상대로 13을 볼 수 있습니다.

특정 컴파일러에서는 먼저 ++ 작업을 먼저 수행 한 다음 추가를 선택합니다. 코드를 다음과 같이 해석합니다.

int i = 5;
++i;
++i;
i = i + i;
cout << i;

그것은 완벽하게 유효합니다.

더 나은 질문은 항상 14?

int i = 5;
i = ++i + ++i;
cout<<i;

i = ++i   + ++i   ;
i = ++(5) + ++(5) ;
i =    6  +    6  ;
i = 12;

i = ++i   + ++i   ;
i = ++i   + ++(5) ;
i = ++i   +   (6) ;
i = ++(6) +    6  ;
i =   (7) +    6  ;
i = 13;

i = ++i   + ++i   ;
i = ++i   + ++(5) ;
i = ++(6) +   (6) ;
i =   (7) +   (7) ;
i = 14;

아마도 아마도 아마도 가능할 것입니다 14, 그것이 만들어지기 때문에 약간 더 의미가 있습니다.

구문 트리의 시야에서 문제를 볼 때 문제에 대한 답이 더 명확 해집니다.


|
=
|
+
|
외교 표현 - 단지 표현

외교 표현 : 단술 조작자 표현

우리의 경우 표현식은 변수 i로 요약됩니다.

이제 두 단수 표현식이 동일한 피연산자를 수정하므로 두 개의 단백 표현식의 결과를 추가하기 전에 단시 표현식을 평가할 때 코드가 두 번 ++ i를 수행하는 것입니다.

코드가하는 일은 실제로입니다

++ i;
++ i;
i = i + i;

i = 5의 경우 의미가 있습니다

i = i + 1; // i <-6
i = i + 1; // i <-7
i = i + i; // i <-14

접두사 증분이 우선하기 때문에 :

int i = 5;
i = i+1; // First ++i, i is now 6
i = i+1; // Second ++i, i is now 7
i = i + i // i = 7 + 7
cout << i // i = 14
 i = i++ + i; //11  

 i = i++ + i++; //12

 i = i++ + ++i; //13

 i = ++i + i++; //13

 i = ++i + ++i; //14    
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top