이러한 && 와 ||의 성질을 단축평가 의미구조(short-circuit semantics)라 합니다.
그래서 C++에서 operator&&와 operator||를 오버로딩하지 않는 것이죠.
연산자 오버로딩을 하면 함수호출 의미구조(function-call semantics)가 되어버리므로 오른쪽 피연산자(여기서는 strlen)가 실행되어 버리므로 원래의 &&와 ||의 기능이 될 수가 없습니다.
short circuit evaluation 하는 언어도 있지만 그렇지 않은 것도 있기 때문에, 이와 같은 표현식은 side effect를 발생할 여지가 있습니다.
Side effect는 이런 경우에 쓰는 용어가 아닌 것으로 압니다.
Call-by-reference나 ++연산자와 같이 값을 반환하는 것과 동시에 변수의 값을 바꾸는 경우를 일컫는 용어입니다.
명령형 언어와 함수형 언어의 차이점을 설명할 때 주로 나오는 용어죠.
unipro wrote:
예를 들어 C는 short circuit evaluation 하는 언어이지만 Pascal은 아니죠.
글쎄요... 저도 10년전에 터보 파스칼부터 시작해서 현재 델파이와 카일릭스를 쓰고 있지만, 제가 알기론 파스칼도 short circuit evaluation입니다.
(물론 ANSI/ISO Pascal만을 따르는 파스칼 컴파일러는 제가 써본적이 없어서 아닐지도 모르겠지만, 상용 파스칼 컴파일러 시장의 압도적인 점유율을 가진 볼랜드 파스칼 컴파일러가 사실상의 표준입니다.)
볼랜드 파스칼의 경우는 short circuit evaluation 기능을 컴파일러 지시자(C/C++로 치면 #pragma)로 on/off를 시킬 수 있는 기능이 있습니다.
unipro wrote:
이것을 하든 안하든 이런 부작용을 야기할 수 있는 표현식은 지양하는 것이 좋을 것 같군요. 즉, short circuit evaluation 하든 안하든지에 대해 독립적으로 올바르게 수행되는 코드를 작성하는 것을 추천합니다.
파스칼의 경우는 님의 의도와 같은 문제점이 있지만, 어차피 short circuit evaluation이 디폴트 설정이므로, 문제될 경우는 별로 없습니다.
C/C++에서는 아예 short circuit이 안되게 바꿀 방법이 없고, 굳이 short circuit을 쓰지 않으려 한다면 && 대신에 &를, || 대신에 |를 쓰던가, 연산자 오버로딩으로 function-call evaluation으로 바꾸면 됩니다.
함수형 언어가 아닌, 명령형 언어에서는 short circuit을 오히려 표준으로 보는 것이 옳다고 생각합니다. short circuit은 컴파일러 입장에서는 일종의 최적화지만, 프로그래머 입장에서는 일종의 syntactic sugar로서, 버그 발생을 줄일 수 있는 장점이 있습니다.
예를 들어 제가 쓴 첫 답글처럼,
char *p;
...
if (p != 0 && strlen(p) > 10)
...
의 경우에는 short circuit이 아니라면 버그가 발생합니다.
이것을 해결하려면 if 문를 두 번 사용하는 지저분한 코드가 되어버리죠.
정리하면, short circuit을 컴파일러 지시어로 on/off할 수 없는 C/C++과 같은 언어에서는 short circuit을 기본으로 생각하고 코드를 작성하는 것이 맞습니다.
특정 언어로 만들어진 코드를 다른 언어로 변환할 경우를 고려해서 범용적인 코드를 만든다면, 특정 언어의 장점을 전혀 살릴 수 없는 코드가 되겠죠.
마치 p2c나 f2c 처럼 파스칼이나 포트란을 기계적으로 C로 변환한 코드처럼 말이죠.
side effect의 뜻을 저는 "부작용"정도로 알고 있었는데, 혹시 제가 잘 못 알고 있는 것인가요? 저도 오랜기간 접해본 단어(?)라서 윗분의 말에 선뜻 "그렇구나~"라고 하기가 어렵군요. 한번 찾아봐야겠습니다. ^^
Quote:
예를 들어 제가 쓴 첫 답글처럼,
코드:
char *p;
...
if (p != 0 && strlen(p) > 10)
...
의 경우에는 short circuit이 아니라면 버그가 발생합니다.
이것을 해결하려면 if 문를 두 번 사용하는 지저분한 코드가 되어버리죠.
위와 같은 경우에는 short citcuit를 쓰더라도 그리 문제가 되지 않을 코드입니다. 조건식이 다른 부분에 영향을 주는 것-예를 들어, 변수의 값을 변경하는 수식-이 없기 때문입니다.
문제는 조건식이 수행되거나 수행되지 않음에 따라서 다른 코드에 영향을 주는 경우이지요.
예를들면,
if ((x > y) || (x++ / 3)) { /* ... */ }
위 코드에서의 경우에 문제가 될 수 있습니다. short circuit에 위해서 x의 값이 바뀔수도 또는 바뀌지 않을 수도 있기 때문입니다. 이것은 의도하지 않은 에러를 발생할 수 있고, 디버깅시에 골머리을 아프게 할 수 있습니다. --; 게다가 위 코드는 boolean 연산이 단지 "간단한" 2개의 수식이라서 그나마 잘 보이지만, 다른 코드에 영향을 줄 부분이 함수로 처리되어 있다거나 수식이 복잡하다거나 하면 죽음입니다.
문제는 조건식이 수행되거나 수행되지 않음에 따라서 다른 코드에 영향을 주는 경우이지요.
예를들면,
if ((x > y) || (x++ / 3)) { /* ... */ }
위 코드에서의 경우에 문제가 될 수 있습니다. short circuit에 위해서 x의 값이 바뀔수도 또는 바뀌지 않을 수도 있기 때문입니다. 이것은 의도하지 않은 에러를 발생할 수 있고, 디버깅시에 골머리을 아프게 할 수 있습니다. --; 게다가 위 코드는 boolean 연산이 단지 "간단한" 2개의 수식이라서 그나마 잘 보이지만, 다른 코드에 영향을 줄 부분이 함수로 처리되어 있다거나 수식이 복잡하다거나 하면 죽음입니다.
제 글의 의도를 정확히 이해하지 못하신 모양이네요.
short circuit은 C/C++의 기본 동작입니다. 이걸 short circuit이 아닌 것으로 가정할 필요가 없다고 생각합니다.
즉, C/C++의 &&, || 연산자는 수학의 논리 연산의 AND, OR가 아니라고 생각해야 된다는 겁니다.
이므로, 일종의 축약된 if ... then 구문으로 보아야 한다는 겁니다.
if ... then ... else를 3항 연산자 ? : 로 쓰는 것과 마찬가지죠.
프로그래머가 이것을 제대로 염두에 두고 있다면, &&과 ||을 AND, OR로 오해함으로 생기는 버그는 발생하지 않을 겁니다.
도데체 왜 C/C++을 다른 언어의 방식대로 사용할 필요성이 있나요?
C가 이전의 언어와 다른 점 중의 하나는
파스칼과 같이 문법의 일관성을 추구하지 않고,
++, --, &&, ||, ? : 등 축약된 syntactic sugar를 제공하여 코딩의 편의성을 제공하였다는 것입니다.
or(||)뿐만 아니라 and(&&)도 마찬가지죠.[code:1]
or(||)뿐만 아니라 and(&&)도 마찬가지죠.
p가 널 포인터라면 strlen는 실행되지 않습니다.
이러한 && 와 ||의 성질을 단축평가 의미구조(short-circuit semantics)라 합니다.
그래서 C++에서 operator&&와 operator||를 오버로딩하지 않는 것이죠.
연산자 오버로딩을 하면 함수호출 의미구조(function-call semantics)가 되어버리므로 오른쪽 피연산자(여기서는 strlen)가 실행되어 버리므로 원래의 &&와 ||의 기능이 될 수가 없습니다.
short-circuit semantics
C에서 논리연산의 기본입니다.
팁이라 하기도 좀 그렇고 programming Q&A쯤 될까요? :wink:
그래서 자바에서는 short circuit 를 피하기 위해서 '&' 나
그래서 자바에서는 short circuit 를 피하기 위해서 '&' 나 '|' 를 사용하죠..
뭐 c에서도 '&' 나 '|' 로 쓸수 있을거 같네요..
팁이기보다 그냥 '주의할 점' 이라 할 수 있겠네요...
op1 || op2 --> op1이 참이면, op2은 판별되지 않고
op1 || op2 --> op1이 참이면, op2은 판별되지 않고 무시됨.
op1 && op2 --> op1이 거짓이면 op2은 판별되진 않음.
논리연산의 기본개념입니다.
C언어를 차용할 필요도 없죠.
위의 코드를 bitwise or 연산으로 고치면...
getc(stdin) == 'a' | CallFunction()
로 고치면,
입력한 결과와 a를 비교하여 return 되는 0 또는 1의 값과
CallFunction()을 수.행.하.고. 난 후 return 되는 0의 값을 bitwise or연산을 취합니다.
이렇게 고치면 bitwise or 연산 전후의 operand들을 모두 비교하기 때문에 처음과 같은 문제점은 발생하지 않겠네요. :P
short circuit
Short circuit...
runtime 시에.. 각각의 predicate expression operand 는 차례로 평가하며
branch에대한 충분한 조건에 도달하면 남아있는 조건을 평가를 않고 취함.
Think..
그냥... 그건 기본 적인거 아니었다요?설마, 그런 목적으로 코드
그냥... 그건 기본 적인거 아니었다요?
설마, 그런 목적으로 코드를 작성하지는 않을 것 같습니다.
(쩝... 사실 전 항상 말이 안되는 코드를 짠다는 T.T )
=========================
CharSyam ^^ --- 고운 하루
=========================
short circuit evaluation 하는 언어도 있지만 그렇지
short circuit evaluation 하는 언어도 있지만 그렇지 않은 것도 있기 때문에, 이와 같은 표현식은 side effect를 발생할 여지가 있습니다. 예를 들어 C는 short circuit evaluation 하는 언어이지만 Pascal은 아니죠.
이것을 하든 안하든 이런 부작용을 야기할 수 있는 표현식은 지양하는 것이 좋을 것 같군요. 즉, short circuit evaluation 하든 안하든지에 대해 독립적으로 올바르게 수행되는 코드를 작성하는 것을 추천합니다.
잠을 못잤더니 정신이 없군요... 음냐...
내 블로그: http://unipro.tistory.com
[quote="unipro"]short circuit evaluation
Side effect는 이런 경우에 쓰는 용어가 아닌 것으로 압니다.
Call-by-reference나 ++연산자와 같이 값을 반환하는 것과 동시에 변수의 값을 바꾸는 경우를 일컫는 용어입니다.
명령형 언어와 함수형 언어의 차이점을 설명할 때 주로 나오는 용어죠.
글쎄요... 저도 10년전에 터보 파스칼부터 시작해서 현재 델파이와 카일릭스를 쓰고 있지만, 제가 알기론 파스칼도 short circuit evaluation입니다.
(물론 ANSI/ISO Pascal만을 따르는 파스칼 컴파일러는 제가 써본적이 없어서 아닐지도 모르겠지만, 상용 파스칼 컴파일러 시장의 압도적인 점유율을 가진 볼랜드 파스칼 컴파일러가 사실상의 표준입니다.)
볼랜드 파스칼의 경우는 short circuit evaluation 기능을 컴파일러 지시자(C/C++로 치면 #pragma)로 on/off를 시킬 수 있는 기능이 있습니다.
파스칼의 경우는 님의 의도와 같은 문제점이 있지만, 어차피 short circuit evaluation이 디폴트 설정이므로, 문제될 경우는 별로 없습니다.
C/C++에서는 아예 short circuit이 안되게 바꿀 방법이 없고, 굳이 short circuit을 쓰지 않으려 한다면 && 대신에 &를, || 대신에 |를 쓰던가, 연산자 오버로딩으로 function-call evaluation으로 바꾸면 됩니다.
함수형 언어가 아닌, 명령형 언어에서는 short circuit을 오히려 표준으로 보는 것이 옳다고 생각합니다. short circuit은 컴파일러 입장에서는 일종의 최적화지만, 프로그래머 입장에서는 일종의 syntactic sugar로서, 버그 발생을 줄일 수 있는 장점이 있습니다.
예를 들어 제가 쓴 첫 답글처럼,
의 경우에는 short circuit이 아니라면 버그가 발생합니다.
이것을 해결하려면 if 문를 두 번 사용하는 지저분한 코드가 되어버리죠.
정리하면, short circuit을 컴파일러 지시어로 on/off할 수 없는 C/C++과 같은 언어에서는 short circuit을 기본으로 생각하고 코드를 작성하는 것이 맞습니다.
특정 언어로 만들어진 코드를 다른 언어로 변환할 경우를 고려해서 범용적인 코드를 만든다면, 특정 언어의 장점을 전혀 살릴 수 없는 코드가 되겠죠.
마치 p2c나 f2c 처럼 파스칼이나 포트란을 기계적으로 C로 변환한 코드처럼 말이죠.
side effect의 뜻을 저는 "부작용"정도로 알고 있었는데, 혹시
side effect의 뜻을 저는 "부작용"정도로 알고 있었는데, 혹시 제가 잘 못 알고 있는 것인가요? 저도 오랜기간 접해본 단어(?)라서 윗분의 말에 선뜻 "그렇구나~"라고 하기가 어렵군요. 한번 찾아봐야겠습니다. ^^
위와 같은 경우에는 short citcuit를 쓰더라도 그리 문제가 되지 않을 코드입니다. 조건식이 다른 부분에 영향을 주는 것-예를 들어, 변수의 값을 변경하는 수식-이 없기 때문입니다.
문제는 조건식이 수행되거나 수행되지 않음에 따라서 다른 코드에 영향을 주는 경우이지요.
예를들면,
위 코드에서의 경우에 문제가 될 수 있습니다. short circuit에 위해서 x의 값이 바뀔수도 또는 바뀌지 않을 수도 있기 때문입니다. 이것은 의도하지 않은 에러를 발생할 수 있고, 디버깅시에 골머리을 아프게 할 수 있습니다. --; 게다가 위 코드는 boolean 연산이 단지 "간단한" 2개의 수식이라서 그나마 잘 보이지만, 다른 코드에 영향을 줄 부분이 함수로 처리되어 있다거나 수식이 복잡하다거나 하면 죽음입니다.
내 블로그: http://unipro.tistory.com
[quote="unipro"]문제는 조건식이 수행되거나 수행되지 않음
제 글의 의도를 정확히 이해하지 못하신 모양이네요.
short circuit은 C/C++의 기본 동작입니다. 이걸 short circuit이 아닌 것으로 가정할 필요가 없다고 생각합니다.
즉, C/C++의 &&, || 연산자는 수학의 논리 연산의 AND, OR가 아니라고 생각해야 된다는 겁니다.
이므로, 일종의 축약된 if ... then 구문으로 보아야 한다는 겁니다.
if ... then ... else를 3항 연산자 ? : 로 쓰는 것과 마찬가지죠.
프로그래머가 이것을 제대로 염두에 두고 있다면, &&과 ||을 AND, OR로 오해함으로 생기는 버그는 발생하지 않을 겁니다.
도데체 왜 C/C++을 다른 언어의 방식대로 사용할 필요성이 있나요?
C가 이전의 언어와 다른 점 중의 하나는
파스칼과 같이 문법의 일관성을 추구하지 않고,
++, --, &&, ||, ? : 등 축약된 syntactic sugar를 제공하여 코딩의 편의성을 제공하였다는 것입니다.
side-effect 라는 말의 뜻은 cedar 님의 말씀이 맞습니다.
side-effect 라는 말의 뜻은 cedar 님의 말씀이 맞습니다.
어떤 식(표현)의 평가(실행) 결과로 그 식의 값이 반환되는 것 이외에 평가 과정에서 발생한 다른 모든 작용을 side-effect 라고 부릅니다.
예를 들어
위 코드의 둘째줄의 식은 0 이라는 값을 반환함과 동시에 a의 값을 1로 바꿉니다. a의 값을 1 증가시킨것이 이 식의 side-effect 입니다.
셋쩨줄은 a 의 값을 표준 출력에 출력합니다. 이 출력 작용이 side-effect 이구요. 이 식의 값은 printf 의 반환 값인 1 이 됩니다.
그리고 short-circuit 은 약간 주의해서 사용해야 할 기능이지 지양해야 할 정도의 기능은 아니라고 생각합니다.
에서 지양해야 할 것은 x++/3 과 같은 표현이지 short-circuit 은 아닌 것 같습니다^^
side effect에 대해서 잘 못 알고 있었군요. ^^ 좋은 정보 주
side effect에 대해서 잘 못 알고 있었군요. ^^ 좋은 정보 주셔서 감사합니다.
코딩의 편이성과 독이성은 많은 부분 trade off 되겠지요. 그리고 사람마다 더 가중을 두는 부분이 다르겠고, 또한 사람에 따라서는 if ... then ... else 보다 &&, || 연산이 잘 들어오는 사람도 있겠지요.
그러나 조금이라도 복잡한 구조에서는 논리연산자보다는 if절이 더 쉽게 읽혀질 것이라 생각됩니다. 특히 &&와 ||를 동시에 사용하는 구조로 된 코드를 볼때는 연필이 필요하더군요.
저의 경우에는 if절로 풀어 쓴 것이 읽기 편하고 코딩시에도 풀어 쓰는 경우가 오타의 횟수가 많기는 하지만 논리적인 오류는 적게 내는 것 같습니다.
한가지 확실한것은 주의해서 사용해야 한다는 것이네요.^^
내 블로그: http://unipro.tistory.com
side effect와 sequence point에 대한 좋은 글입니다.
side effect와 sequence point에 대한 좋은 글입니다.
han.comp.lang.c 뉴스그룹의 관련 글들을 뒤지던 중 발견했습니다.
http://www.embedded.com/story/OEG20020625S0041
댓글 달기