[C] 연산자 우선순위 문제
질문 제목
||연산과 &&연산
질문 요약
질문 내용
결과값이 왜 이렇게 나오는 거죠??
설명좀 부탁드립니다.
설명
연산자 우선순위 문제인데...
일단 C언어의 연산자 우선순위는 다음과 같다.
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도 증가되어야 하는데
결과는 그게 아니다... 그럼 연산자 우선순위가 잘못된 것인가? 그것도 아니다.
정답은 컴파일러에 있다.
문제와 똑같은 코드인데 ()만 추가했다. ()는 우선순위가 절대적으로 빠르기 때문에 ()를 추가해서 결과를 확인해 본 것이다.
위 코드를 실행해보면 연산자 우선순위가 제일 높은 ()로 묶었음에도 불구하고 같은 결과값이 나오는데
이걸로 유추해 볼때 뒤 ++y && ++z는 아예 분석조차 안된다고 생각할 수 있다.
즉 컴파일러가 코드 분석을 할 때 좌측에서 우측으로 분석이 되는데
++x ||를 분석하는 순간 우측은 분석할 필요도 없이 결과값이 무조건 참이 나오기 때문에
++x || 다음 구문은 해석조차 하지 않고 다음 구문으로 넘어가 버리는 것 같다.
구문 분석 단계에서 결정이 나기 때문에 연산자 우선순위는 필요가 없다.
일단 컴파일러가 구문 분석을 해야 그 이후에 연산자 우선순위를 따져 빠른 연산부터 수행을 하는데
이와같은 경우에는 아예 뒤쪽은 분석도 안하고 넘어가 버리는 것 같다.
이는 컴파일러의 컴파일 방식이므로 컴파일러마다 결과가 다르게 나올 수 있다.
확인해 본 결과 gcc와 VS2010에서는 동일한 결과가 나왔다.
컴파일이 이렇게 수행되는 이유는 컴파일 속도를 조금이라도 높게 하기 위한 것이라고 추측된다.
마지막으로 간단하게 예를 들어 설명 드리자면
k = 0 * ((256 - 36) / ((5634 % 3) + 234 / (7 * (3 + 5)))); 뭐 이러한 공식이 있다고 칠 때
컴퓨터가 푸는게 아니라 사람이 푼다고 생각했을 때 어느 사람이든 맨 앞에 0 * 를 보는 순간 뒤에 무슨
내용이 나오던지 답은 0이 될 것이기에 뒤는 보지도 않고 k = 0 이라고 할 것이다.
(물론 뒷 부분을 전부 계산하고 나서 마지막에 0과 곱해서 답을 0이라고 할 수도 있지만 시간이 걸릴것이다.)
뒤에 ()로 묶인 + 연산이 빨리 되던지 곱하기가 빨리 되던지 따윈 중요하지 않다 뒤에 연산 결과가 어떻게 나오든 결과는 0이니까...
컴파일러도 이와 마찬가지로 앞 부분만 봐서 결과가 정해지면 뒤의 내용는 구문 분석조차 하지 않고 넘어가는것 같다.
위 내용은 어디까지나 결과만을 가지고 추측한 내용이기 때문에 틀릴 수 있다.
위 내용에 틀린 부분이 있거나 정확한 이유를 아시는 분은 댓글을 통해 태글, 수정 및 지적해 주시면 감사하겠습니다.
||연산과 &&연산
질문 요약
#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언어의 연산자 우선순위는 다음과 같다.
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이니까...
컴파일러도 이와 마찬가지로 앞 부분만 봐서 결과가 정해지면 뒤의 내용는 구문 분석조차 하지 않고 넘어가는것 같다.
위 내용은 어디까지나 결과만을 가지고 추측한 내용이기 때문에 틀릴 수 있다.
위 내용에 틀린 부분이 있거나 정확한 이유를 아시는 분은 댓글을 통해 태글, 수정 및 지적해 주시면 감사하겠습니다.
댓글
댓글 쓰기