请问为什么下面代码输出的值为22?
求给出分析过程
#include<stdio.h>
int main(void)
{
int i=5,j=5;
int p;
p=(++i)+(++i)+(++i);
printf("p=%d",p);
return 0;
}
阿神2017-04-17 15:33:45
식에서 동일한 변수에 대한 여러 의 평가 순서는 불확실합니다. 이 동작은 정의되지 않습니다. 컴파일러에 따라 부작용이 있는 코드를 작성하는 것이 좋습니다. .
평가 순서는 위키를 참고하세요
怪我咯2017-04-17 15:33:45
시험문제인 경우 관련 시험자료를 참고하시기 바랍니다.
C 11/14 및 C11에 대한 올바른 아이디어는 다음과 같습니다.
표현식 ( i) ( i) ( i)
에 관련된 순서 규칙은 증분 우선 순서 규칙(부작용이 값보다 먼저 계산됨)과 연산자의 순서 규칙(피연산자의 값이 연산자 결과 값보다 먼저 계산됨)입니다. 계획된).
이로 결정할 수 있는 계산 순서: 이 식에서는 관련 i
의 값이 계산되기 전에 모든
의 부작용과 값이 계산됩니다(
에는 부작용이 없습니다). ) 및 그 부작용은 값(즉, 먼저 증가)보다 먼저 계산됩니다.
의 연관성(왼쪽에서 오른쪽으로)에 따르면 첫 번째
의 값이 계산된 후 두 번째
의 값이 계산된다는 결론을 내릴 수 있습니다.
계산 순서를 알 수 없음: 두 i
의 값 계산과 부작용 사이에는 명확한 순서 관계가 없습니다.
위의 제한 사항을 기반으로 직관적으로 일련의 가능한 계산 프로세스를 나열할 수 있습니다.
6 7 8 = 13 8
6 8 7 = 14 7
7 6 8 = 13 8
...
그러나 문제는 C 11/14 표준에 다음과 같은 규칙이 있다는 것입니다.
(§1.9/15)[...]스칼라 개체에 대한 부작용이 동일한 스칼라 개체에 대한 다른 부작용이나 동일한 스칼라 개체의 값을 사용한 값 계산에 비해 순서가 없는 경우 , 동작이 정의되지 않았습니다.
C11 표준에는 다음과 같은 규칙이 있습니다.
(§6.5/2)스칼라 객체에 대한 부작용이 동일한 스칼라 객체에 대한 다른 부작용이나 동일한 스칼라 객체의 값을 사용한 값 계산과 관련하여 순서가 없는 경우 동작은 다음과 같습니다. 정의되지 않았습니다.[...]
그리고 이 표현식에서 두 ' i' 사이의 부작용 순서가 결정되지 않았기 때문에 이는 C 11/14 및 C11에서 정의되지 않은 동작입니다.
C 11 및 C11 이전의 규칙은 여기에서 논의되지 않지만 해당 표준에 따르면 이들 역시 정의되지 않은 동작입니다.
마지막 장황한 문장은 정의되지 않은 동작입니다. C 11 표준에는 다음과 같은 규칙이 있습니다.
(§1.3.24) 정의되지 않은 동작
이 국제 표준이 요구 사항을 부과하지 않는 동작
[참고: 이 국제 표준이 동작에 대한 명시적인 정의를 생략하거나 다음과 같은 경우 정의되지 않은 동작이 예상될 수 있습니다. 프로그램이 잘못된 구성이나 잘못된 데이터를 사용하는 경우 허용되는 정의되지 않은 동작은 예측할 수 없는 결과로 상황을 완전히 무시하는 것부터 문서화된 번역 또는 프로그램 실행 중에 동작하는 것까지입니다. 환경의 특성(진단 메시지 발행 여부에 관계 없음), 번역 또는 실행 종료(진단 메시지 발행 포함) 많은 잘못된 프로그램 구성은 진단이 필요한 정의되지 않은 동작을 발생시키지 않습니다. — 끝 참고 ]
C11 표준에는 다음과 같은 규칙이 있습니다
(§3.4.3)
1 정의되지 않은 동작
이 국제 표준에서 요구 사항을 부과하지 않는 이식 불가능하거나 잘못된 프로그램 구성 또는 잘못된 데이터를 사용할 때 발생하는 동작
2 참고 정의되지 않은 가능한 동작은 예측할 수 없는 결과로 상황을 완전히 무시하는 것부터 환경에 따라 문서화된 방식으로 변환 또는 프로그램 실행 중에 동작하는 것까지 다양합니다. 또는 진단 메시지 발행 없이), 번역 또는 실행 종료(진단 메시지 발행).
즉, 표준은 정의되지 않은 동작에 대한 요구 사항을 제시하지 않으며, 컴파일러나 실행 중인 플랫폼은 컴파일 타임이나 런타임 시 정의되지 않은 동작의 동작에 동의할지 여부에 동의할 수 있습니다. 규칙이 없으면 프로그램의 동작을 완전히 예측할 수 없습니다.
탄예(안개)의 생각을 따르면, (아마도) 연산자 (왼쪽 조합)의 조합을 바탕으로 등가식 (( i) ( i)) ( i)
이 얻어진다. 그러면 왼쪽의 두 개의 i
이 먼저 계산된 것으로 추론됩니다(짙은 안개). 이는 (7 7) ( i)
(큰 것)과 동일하며 이는 다음과 같습니다. (7 7) 8
. 22
天蓬老师2017-04-17 15:33:45
첫 번째 i가 작업에 참여한 결과는 6이고, 두 번째 i가 작업에 참여한 결과는 7이므로 첫 번째도 마찬가지로 7이 됩니다. 연산은 7 8이므로 처음 두 개가 8이 되고 최종 결과는 24입니다. 저는 VS를 사용하고 있으며 이는 C 로 측정됩니다.
VS도 마찬가지고, C를 사용한 결과는 아래와 같습니다
伊谢尔伦2017-04-17 15:33:45
위 답변이 정답이라 답변을 철회했습니다.
이 문제로 계속 고민한다면 사용 중인 컴파일러에 대한 어셈블리로 코드를 컴파일하고 정확히 무슨 일이 일어나는지 확인할 수 있습니다
PHPz2017-04-17 15:33:45
음. . 너무 많이 말했지만 사실 문제는 계산 순서에 관한 것이 아닙니다. 덧셈 연산의 순서는 왼쪽에서 오른쪽입니다.
p=( i) ( i) ( i);
처음 추가하면 얼핏 6 7처럼 보이지만, 두 번째 i의 자체 증가로 인해 앞에 i(6)이 생성됩니다(첫 번째 i). )도 7이 됩니다. 그러면 첫 번째 단계의 합은 14가 됩니다.
그러면 14에 세 번째 i(8)를 더하면 22가 됩니다.
이 답변은 SX 교과서 일치에 국한됩니다. 실제 적용에서는 다리가 부러질 것입니다! 물론, 다른 컴파일러도 그에게 표현을 제공할 것입니다.