전위 또는 후위연산자와 비교 연산자가 동시에 존재할때 해석방법이 어떻게 되나요?

jhkim123의 이미지

안녕하십니까 저는 전산직 공부하고 있는 공시생입니다
학교때 쓰던 책도 살펴보고 비주얼 스튜디오도 돌려서 디버깅을 해봤는데
확신이 안되어 쪼개서 설명 해주셨으면 해서 여기에 질문 올립니다

#include <stdio.h>
int main()
{
    int i = 3;
    int j = 4;
    if((++i > j--) && (i++ < --j)) i = i-- + ++j;
    else j = i-- - --j;
    printf("%d₩’. i);
}

시험문제는 띄어쓰기나 중괄호를 안쓰는 형태로 나오네요
비교 당시에 if((3 > 4) && (3 < 4)) i = i-- + ++j; 이렇게 비교한후 증감이 이루어지나요?

*여기에 글 처음쓰니 양식 같은게 틀린거 있으면 말해주시면 글 수정하겠습니다

jick의 이미지

문제가 잘못됐네요.

i = i-- + ++j 같은 코드는 잘못된 코드입니다. ++/-- 연산자가 쓰인 변수를 같은 statement 안에서 또 업데이트하려고 하면 안됩니다. (정확히 말하면 좀 더 복잡한데 저도 자세한 규칙은 잘 모르니 대충 쓰겠습니다. -_-)

if 문 안의 조건은 문제가 없습니다. &&는 무조건 앞부분을 먼저 계산하고 그 결과가 참일 때만 뒷부분을 계산하는 성질이 있기 때문에 결국 이렇게 됩니다:

(1) 첫번째 조건: ++i > j--
여기서 ++i의 값은 4, j--의 값은 역시 4입니다. 물론 이 식을 수행한 다음 i, j의 값은 각각 4, 3이 됩니다. 보시다시피 ++i > j--는 거짓이기 때문에 두번째 조건은 수행되지 않습니다.

(2) 여기서 else 문으로 넘어가는데, --j를 수행하면서 j의 값을 동시에 변경하려 하고 있습니다. 잘못된 코드입니다.

익명 사용자의 이미지

1. C99의 기준에서, 인접한 두 sequence point 사이에서 object는 최대 단 한 번만 변경될 수 있습니다.

1) (++i > j--) && (i++ < --j)의 경우, && 연산자는 왼쪽 operand를 계산한 후 sequence point를 찍기 때문에 문제 없습니다.

2) i = i-- + ++jj = i-- - --j는 각각 i와 j를 인접한 sequence point 안에서 두 번 변경하고 있기 때문에 undefined behavior입니다.

3) 현실적으로 보면, if statement의 조건은 명백히 거짓이고, 따라서 else 부분이 실행되는데 여기서 문제가 되는 부분은 j의 변경이니까, i는 그냥 무난히 3이 될 거라고 생각할 수도 있습니다. 제가 gcc로 컴파일해서 돌려 봐도 그렇게 나오는군요.

이건 아무리 undefined behavior라고 해도 컴파일러가 딱히 더 비이성적으로 동작할 필요는 없을 거라는 믿음 하에서 그렇게 생각하는 것입니다. 하지만 undefined behavior를 유발하는 프로그램은 이론상 어떤 일이든 할 수 있고, 결과적으로 i가 어떤 값을 가지든 뭐라 불평할 수가 없지요.

2. C11에서 이 규칙은 약간 바뀌었는데, 간단히 요약하면 인접한 sequence point 사이에서 어떤 scalar object에 대해 side effect가 두 번 이상 일어났다고 하더라도 그 사이에 순서가 잘 정의되면 허용되는 규칙이 생겼습니다.

이 규칙을 따지려면 expression을 이루는 구성요소 하나하나에서 sequenced before/after를 따져봐야 해서 상당히 짜증스러운데, 대충 살펴보니 j = i-- - --j에서 j에 대해 발생하는 두 side effects 사이엔 정해진 순서가 없는 것 같네요. 그러면 여전히 undefined behavior입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.