질문 제목
||연산과 &&연산
질문 요약
#include<stdio.h>
int main()
{
int x,y,z,k;
x = 1;
y = 2;
z = 3;
k = ++x || ++y && ++z;
printf("%d %d %d %d\n",k,x,y,z);
return 0;
}
// 결과 값 : 1 2 2 3
질문 내용
결과값이 왜 이렇게 나오는 거죠??
설명좀 부탁드립니다.
설명
연산자 우선순위 문제인데...
일단 C언어의 연산자 우선순위는 다음과 같다.
그리고 이 문제를 알기 위해서는 하나를 더 알아야 하는데...
컴파일러마다 다를수도 있지만 Visual Studio에서는 앞 조건만 봐서 무조건 결과가 참이 나오면 뒷 부분은 연산이 되지 않는다...
무슨 얘기인가 하면 x = 1, y = 1, z = 1 이 있다고 하고 if ( ++x || ++y || ++z ) 이렇게 if문이 있으면 맨 앞 ++x를 보면 참이되고
|| 연산자에 의해서 뒷 부분에 어떠한 값이 나와도 참이된다 그럼 ++y, ++z는 아예 분석조차 되지 않는다.
따라서 저 if문 다음에 x, y, z를 출력해 보면 x는 1이 증가해서 2가 되어 있지만 y, z는 그대로 1인것을 확인할 수 있다.
위에서 설명한 것을 먼저 파악하고 계속해서 문제를 보면
k = ++x || ++y && ++z; 이 라인에서 ++x 만 증가하고 y와 z는 그대로라고 생각할 수 있다.
(k의 값은 연산 결과가 참이기 때문에 1이 들어갈 것이라고 짐작할 수 있다.)
그럼 결과가 1, 2, 2, 3이 맞다.
그러나! 여기서 연산자 우선순위를 다시 한번 확인해보자... 분명히 || 보다 &&가 더 빠르다!!!
그럼 y와 z를 먼저 비교하고 다음으로 x와 비교하게 되기 때문에 당연히 y와 z도 증가되어야 하는데
결과는 그게 아니다... 그럼 연산자 우선순위가 잘못된 것인가? 그것도 아니다.
정답은 컴파일러에 있다.
#include <stdio.h>
int main()
{
int x = 0, y = 0, z = 0, k = 0;
x = 1;
y = 1;
z = 1;
k = (++x || (++y && ++z));
printf("k[%d] x[%d] y[%d] z[%d]\n", k, x, y, z);
return 0;
}
문제와 똑같은 코드인데 ()만 추가했다. ()는 우선순위가 절대적으로 빠르기 때문에 ()를 추가해서 결과를 확인해 본 것이다.
위 코드를 실행해보면 연산자 우선순위가 제일 높은 ()로 묶었음에도 불구하고 같은 결과값이 나오는데
이걸로 유추해 볼때 뒤 ++y && ++z는 아예 분석조차 안된다고 생각할 수 있다.
즉 컴파일러가 코드 분석을 할 때 좌측에서 우측으로 분석이 되는데
++x ||를 분석하는 순간 우측은 분석할 필요도 없이 결과값이 무조건 참이 나오기 때문에
++x || 다음 구문은 해석조차 하지 않고 다음 구문으로 넘어가 버리는 것 같다.
구문 분석 단계에서 결정이 나기 때문에 연산자 우선순위는 필요가 없다.
일단 컴파일러가 구문 분석을 해야 그 이후에 연산자 우선순위를 따져 빠른 연산부터 수행을 하는데
이와같은 경우에는 아예 뒤쪽은 분석도 안하고 넘어가 버리는 것 같다.
이는 컴파일러의 컴파일 방식이므로 컴파일러마다 결과가 다르게 나올 수 있다.
확인해 본 결과 gcc와 VS2010에서는 동일한 결과가 나왔다.
컴파일이 이렇게 수행되는 이유는 컴파일 속도를 조금이라도 높게 하기 위한 것이라고 추측된다.
마지막으로 간단하게 예를 들어 설명 드리자면
k = 0 * ((256 - 36) / ((5634 % 3) + 234 / (7 * (3 + 5)))); 뭐 이러한 공식이 있다고 칠 때
컴퓨터가 푸는게 아니라 사람이 푼다고 생각했을 때 어느 사람이든 맨 앞에 0 * 를 보는 순간 뒤에 무슨
내용이 나오던지 답은 0이 될 것이기에 뒤는 보지도 않고 k = 0 이라고 할 것이다.
(물론 뒷 부분을 전부 계산하고 나서 마지막에 0과 곱해서 답을 0이라고 할 수도 있지만 시간이 걸릴것이다.)
뒤에 ()로 묶인 + 연산이 빨리 되던지 곱하기가 빨리 되던지 따윈 중요하지 않다 뒤에 연산 결과가 어떻게 나오든 결과는 0이니까...
컴파일러도 이와 마찬가지로 앞 부분만 봐서 결과가 정해지면 뒤의 내용는 구문 분석조차 하지 않고 넘어가는것 같다.
위 내용은 어디까지나 결과만을 가지고 추측한 내용이기 때문에 틀릴 수 있다.
위 내용에 틀린 부분이 있거나 정확한 이유를 아시는 분은 댓글을 통해 태글, 수정 및 지적해 주시면 감사하겠습니다.
'C > Study' 카테고리의 다른 글
컴파일과 빌드의 차이점 (0) | 2024.12.21 |
---|---|
[C] 오류와 경고의 차이점 (0) | 2024.12.21 |
[C] C언어의 장점 (1) | 2024.12.20 |
[C] C프로그래밍이 실행되기까지 (0) | 2024.12.20 |
[C] __int64 (0) | 2024.12.20 |