논리 연산자의 우선순위/계산

bommy의 이미지

안녕하세요! c 처음 배우는 대학생입니다
논리 연산자라는 것을 공부하면서 의문점이 생겨 질문드립니다ㅠㅠ

- 논리 연산자의 우선순위
x = y = z = 1;
result = ++x || ++y && ++z;

의 식에서 &&이라는 논리 연산자가 ||이라는 논리 연산자보다 우선순위가 높기 때문에
저는 ||보다 (++y && ++z)의 식이 먼저 계산될 것이라고 생각했지만, ++x || ++y를 먼저 연산한
결과가 나왔습니다... 저는 프로그래밍이 항상 우선순위에 따라서 연산이 되는 것이라고 생각했는데
왜 왼쪽부터 계산한 결과가 나오는 것인가요??

+) ||이나 &&이 시퀀스 포인트로써의 역할을 하기 때문에, ||이전에서 식이 연산되어야 하기에
우선순위가 무시된 것이고, 시퀀스 포인트로써 기능하지 않는 연산자들의 우선순위는 제가 원래
생각했던 것처럼 연산의 우선순위를 정해주는 역할을 하는 것인가요??

익명 사용자의 이미지

C언어의 미궁에 들어온 것을 환영합니다. :)

1. 속칭 연산자 우선 순위란, 어떤 연산자가 피연산자와 먼저 결합하는지를 결정할 뿐입니다.

예컨대 a + b * c와 같은 코드에서, 곱셈 연산자가 피연산자에 먼저 결합하므로 마치 a + (b * c)와 같이 동작합니다.

2. 연산자 우선 순위는 각 피연산자의 값 계산 순서나 부수적 효과(side effect)의 순서를 결정하지 않습니다.

앞서와 비슷한 예로, f1() + f2() * f(3)를 봅시다.

연산자 우선 순위에 의해 이는 물론 f1() + (f2() * f(3))와 같습니다.

그러면 함수 f2 혹은 f3이 f1보다 먼저 호출 될까요? 그렇지 않습니다.

C언어에서 부분 표현식의 값 계산이나 부수적 효과는 별도의 규칙이 없는 한 정해져 있지 않으며, 컴파일러가 임의로 결정할 수 있습니다.

3. 제시된 예는 분명히 && 연산자가 우선 순위를 가지며, 따라서 먼저 묶입니다.

아래 예를 보시죠.

printf("1 || 1 && 0 = %d\n", 1 || 1 && 0);
printf("(1 || 1) && 0 = %d\n", (1 || 1) && 0);
printf("1 || (1 && 0) = %d\n", 1 || (1 && 0));

1 || 1 && 01 || (1 && 0)와 같이 묶인다는 데 의심의 여지는 없을 겁니다.

그런데 &&|| 연산자는 앞서 말씀드렸던 별도의 규칙 중 하나인 단축 평가를 지원합니다.
즉 이들 연산자는 반드시 왼쪽 피연산자를 먼저 평가하고, 그 이후에 결과에 따라 오른쪽 피연산자를 평가하게 됩니다.

따라서, ++x || ++y && ++z++x || (++y && ++z)와 같이 묶이지만...

(1) ++x || (++y && ++z)가 평가될 때, ||++x를 먼저 평가하고, 그게 거짓인 경우에만 ++y && ++z를 평가합니다.
(2) ++y && ++z가 평가될 때, &&++y를 먼저 평가하고, 그게 참인 경우에만 ++z를 평가합니다.

최종적으로 보면 피연산자들 중 ++x만 평가 될 것이고, 따라서 x만 1 증가하며 result는 참(1)이 되겠군요.

익명 사용자의 이미지

f1() + f2() * f(3) => f1() + f2() * f3()
f1() + (f2() * f(3)) => f1() + (f2() * f3())

bommy의 이미지

답변해주셔서 정말 감사합니다!!
제가 이틀 동안 추가적으로 생각해보았는데요...
위의 연산에서 || 이후에 &&의 연산자가 사용되었기에, ++x || (++y && ++z)처럼 생각이 가능했고,
앞 부분의 연산 만으로 답이 결정되는 경우에는 뒤의 ()의 연산 자체가 필요 없었지만,
만약 __&&__||__의 식이 존재한다고 했을 때,우선순위를 생각해본다면 (__&__)||__이기에 &&의 앞의 값 만으로 답이 결정된다면 &&과 ||의 사이 식만 연산하지 않고 바로 (0||__)의 식을 계산하는 것인가요???
정말 오래 생각했는데 이게 맞는 것인지 모르겠네요 ㅠㅠ

ymir의 이미지

논리 연산자는 그 자체가 sequence point 이기 때문에, 왼쪽 피연산자부터 차례대로 평가됩니다.
거기에 short circuit evaluation 이 적용되는데, 평가된 값이 나머지 피연산자에 영향을 받지 않는 경우에는 나머지를 더 이상 평가 하지 않는 것입니다.
따라서 true && a || b 에서, a 가 true 면 true || b 가 되므로 b 를 평가할 필요가 없고, a 가 false 이면 false || b 가 되므로 b 를 평가해야 됩니다.
만약 false && a || b 라면, a 의 값과 상관 없이 false || b 가 되므로, a 는 평가하지 않고, b 만 평가하게 됩니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.