C언어 if문 내의 논리연산자 스타일에 대한 질문입니다.
동아리에 한 후배가 쓴 글인데, 회원들사이에 논의가 있어서 여기에 올립니다.
if (filp->f_op && filp->f_op->flush) { lock_kernel(); retval = filp->f_op->flush(filp); unlock_kernel(); }
이런 코드에서요. if문 내를 보면 먼저 filp->f_op를 배교하고 이것이 참인 경우만 두번째 filp->f_op->flush를 확인하잖아요.
그런데 이런 스타일의 구문이 과연 좋은지에 대한 의문입니다.
어떤 스타일이 좋은지 의견 부탁드립니다.
----------------------------------------------------------------------
참고로 제 생각은, 이렇습니다.
저자신은 앞의 방식이 몇가지 불안정한 요소가 있는것으로 알고 있거든요.
일단 C에서 제공하는 &&나 ||는 명백한 의미의 and나 or가 아닌 것으로 알고 있습니다. &&->and, ||->or 라면 &&와 ||의 좌변과 우변은 교환법칙이 성립해야 하는데 C에서는 안되는 것으로 알고요. (결국 C에서 &&는 andthen, ||는 orlese)
따라서 이런 기법에 익숙해진 사용자가 다른 언어를 사용시 실수할 가능성이 높다고 생각합니다. (교환법칙이 성립하는 언어의 경우 컴파일 최적화시 교환법칙을 수행할 경우)
그리고 True, False의 경우도 따로 type을 지정해두고 사용해야 안전하지 않을지 생각합니다.
반면에 이런 생각도 있습니다. C에서 이런 구문을 제공하는 것은 다 이유가 있기 때문이 아닐까 합니다. HW적으로도 순차적인 처리를 수행한다면 다음 로직이 맞는거 같기도 합니다. 그리고 간단 명료해 보이기도 하고요.
----------------------------------
ps) 제가 쓴 의견이 명확히 않아서 수정했습니다. :wink:
해당 언어에 대한 이해가 있는 사람이 보자마자 이해 가능한 코딩 스타일은
해당 언어에 대한 이해가 있는 사람이 보자마자 이해 가능한 코딩 스타일은 어떤 것이든 좋습니다. 물론 문법은 맞아야 겠죠.
int x = (c++) + (c++)*(--c);
와 같은 코드만 아니라면 좋다고 생각합니다.
일반적으로 사용되는 스타일 이면서 보기 좋고 오해의 여지가 없는 스타일을 선호 합니다.
위의 예로 드신 코드 스타일은 C에서 문법적으로 완전하며 추천되는 스타일 입니다.
&&, || 에 대한 연산 순서와 값 구하는 방법이 표준에 명확이 정의 되어 있기 때문에 오해의 여지는 없습니다.
의 스타일도 일반적 입니다. 하지만 한단계 더 들어가 있어 처음 스타일을 더 좋아하시는 분들도 많습니다.
----------------------------------------
http://moim.at
http://mkhq.co.kr
Re: C언어 if문 내의 논리연산자 스타일에 대한 질문입니다.
/는 정확한 의미의 연산자가 맞지만 교환법칙이 성립하지 않습니다.
&&나 ||를 논리연산자로만 사용한다면 진정한 연산자라고 불러줘야 한다는 쪽에 몰표 던집니다.
문제 제기가 컴파일러의 이러한 동작 방식에 대한 것인지 아니면 이런 특성
문제 제기가 컴파일러의 이러한 동작 방식에 대한 것인지 아니면 이런 특성을 직접적으로 활용하는 것의 선악에 대한 것인지 약간 불분명하긴 하지만 후자라고 가정하고 본다면...
일단 교환법칙이 성립하긴 합니다. 바꿔도 최종 평가 결과는 같죠. 사실 따지고보면 생각하는 방식이 사람하고 똑같습니다. 그냥 굳이 평가할 필요가 없는 부분을 생략하는 것 뿐입니다.
그런데 이걸 이용하는 것이 좋은가 아닌가.. 일단 다른 언어들도 사용 순위 10위권 정도의 언어는 모두 저런 식으로 평가하는 것으로 알고 있습니다. 딱히 언어가 바뀌는 것으로 인한 실수 가능성을 따지기는 어려울 것 같습니다. 그리고 사실 논리적으로 틀린 것은 아니라서 그다지 나쁘진 않다는 생각입니다. 문제가 생기는 것은 if문 안에서 실행하는 평가식으로 인해 무언가 상태가 바뀌는 경우인데 사실 if 조건 안에 mutator를 여러 개 넣는 것은 그 자체가 좋다고 볼 수 없죠. 저런 순서에 의지하게 코딩하는 습관보다 두 평가식이 모두 평가될 꺼라는 가정을 하는 습관이 더 안 좋은 습관이기 때문에 저런 코딩 방식을 권장하진 않을지라도 막을 필요는 없다고 봅니다.
Re: C언어 if문 내의 논리연산자 스타일에 대한 질문입니다.
dgsquare님의 말 뜻은 "정확한 의미의 and 연산자, or 연산자라면"으로 이해하시면 될 것 같습니다.
흠.. 저는 short-circuit evaluation은, 부작용이 있
흠.. 저는 short-circuit evaluation은, 부작용이 있는 코드를 일부러(?) 만들어 쓰지 않는 이상 문제 없다는 쪽에 표를 던지겠습니다..
Re: C언어 if문 내의 논리연산자 스타일에 대한 질문입니다.
이런 short circuit 방식의 평가는 C에서만 쓰는 것은 아닌 것으로 알고 있습니다.
C++은 물론이고, 기억을 더듬어보면 Fortran에서도 그랬던 것 같습니다. 방금
생각났는데 perl도 그렇군요. 사실 short circuit은 너무나 당연한 것이어서 이것을
쓰지 않는 언어가 이상하다고 생각합니다.
그럴지도 모르겠습니다. 실제로 boolean 형을 따로 갖고 있는 언어도 있습니다.
하지만 C는 안전성보다는 효율, 자유로움 등을 중시하는 언어임을 고려하면 이해를
못할 것도 없겠습니다. 참고로 C99에서는 _Bool형이 있습니다.
Re: C언어 if문 내의 논리연산자 스타일에 대한 질문입니다.
일단 답변감사하구요 ^^; 수정하였습니다. creativeidler님이 예기하신 의미가 맡습니다. 제가 예기하려고 했던것은 &&가 명백한의미의 'and'가 아니고 ||도 명백한 의미의 'or'는 아니라는 것입니다. 그래서 괄호안에 C에서 쓰이는 의미를 적어두었던 것이구요. 급히적다보니 글의 의미가 불명확했더거 갔네요 ^^;
그러고 보니 왜 여러 언어에서 and대신에 andthen을 쓰는지 궁금하네요. -,.-;; (질문이 문어발처럼----)
ps) 이런 방식을 short circuit 방식이라구 하는군요 :D
그야 물론 경제성 때문이죠. exception handling이 있는 언
그야 물론 경제성 때문이죠. exception handling이 있는 언어에서는 나름대로 편리하기도 하구요. 이를테면 자바에서 흔히 보는 코드 중에
같은 게 있죠. 두 식을 둘다 평가해버린다면 이런 문장을 if 두 개로 나눠 써야겠지만 short circuit 덕에 같이 쓸 수 있습니다. null인 경우를 무시해도 되는 경우는 저런 코드가 괜찮죠.
그리고 의미상으로는 분명히 and의 의미가 맞습니다.
답변감사드립니다 ^^;결국은 편의성과 명백한 의미 사이의 관계인것 같
답변감사드립니다 ^^;
결국은 편의성과 명백한 의미 사이의 관계인것 같네요. short circuit로 실행된다는 것만 이해하면 큰 문제는 없을 것 같습니다. 많은 도움 되었습니다.
http://en.wikipedia.org/wiki/Lazy_evalua
http://en.wikipedia.org/wiki/Lazy_evaluation#Minimal_evaluation
short circuit evaluation의 장점(?)에 대한 언급이 있길래 링크 겁니다.
일단 C로 시야를 좁혀 놓고 말한다면, C의 표준은 분명히 다음과 같이
일단 C로 시야를 좁혀 놓고 말한다면, C의 표준은 분명히 다음과 같이 정확하게 정의하고 있으므로
C 프로그래머는 &&을 사용하면서 전혀 불안을 느낄 필요가 없습니다. 또한 많은 코드들이 이러한 동작에 바탕을 두고 쓰여져 있으므로 차후 표준에서도 섣불리 바뀌지 않을 것은 분명합니다.
--------
'만약 우리가 새로운 언어를 정의해서 만든다고 할때 어떤 방식이 더 좋을까?'라고 묻는 것이었다면, 다음과 같은 선택이 가능할 것입니다.
1. 전항을 먼저
2. 후항을 먼저
3. 랜덤하게 선택
4. '지능적으로 선택'
5. undefined.
만약 프로그래머의 코드에 대한 통제력을 중시한다면 1번과 2번을 선택할 수도 있겠고, 언어 자체의 최적화 가능성을 중시한다면 3-5번을 선택할 수도 있겠지요. C언어는 전자 쪽을 택했을 뿐입니다.
C언어도 어떤 사항에 대해서는 5번과 같은 선택을 하고 있습니다. 바로 함수 인자들의 평가 순서를 정할 때 입니다.
f(a, b, c);
위와 같은 코드가 있을 때, a, b, c 중에서 어떤 것이 먼저 평가될 것인지는 정해져 있지 않습니다(unspecified인지 undefined인지는 잘-_-;).
실제로 어떤 ARM C 컴파일러에서는 단순히 왼쪽에서 오른쪽으로, 혹은 오른쪽에서 왼쪽으로 평가하기보다는 'hardest'한 인자부터 먼저 평가한다고 하더군요. 이 컴파일러에서는
f(g(), i+1)
와 같은 코드가 있을 때 g()를 가장 먼저 평가합니다. 만약 i+1부터 평가한다면 g()를 평가하기 전에 레지스터의 값을 따로 저장할 필요가 있기 때문입니다.
결국은 프로그래밍 언어의 철학에 달린 일입니다. 자유와 엄밀함 중에서 어떤 것을 선택할 것인가? 의 문제인 셈이죠.
&&와 ||를 쓸때 값을 바꾸는 행위만 하지 않는다면 특별
&&와 ||를 쓸때 값을 바꾸는 행위만 하지 않는다면 특별히 문제는 없을 것 같습니다.
- 죠커's blog / HanIRC:#CN
댓글 달기