c언어에서 ++b + ++b 가 어떻게 계산되는건가요?

hyangil의 이미지

c언어에서 ++b + ++b 가 어떻게 계산되는건가요?

예를 들어

int a;
int b= 3;

a = ++b + ++b;

이때 a 값이 예상했던 9가 아니라 10이 나옵니다.

이건 왜 이런걸까요? ㅜㅡ

chadr의 이미지

연산자 우선순위에 의해서 아래와 같이 계산되는듯 합니다.

1.첫번째 ++b -> 4
2.두번째 ++b -> 5
3.1과2의 합을 위해 +연산 -> b(5) + b(5) -> 10

어셈코드를 보니 아래와 같이 되는군요

00411CE5  mov         eax,dword ptr [b] -> 첫번째 ++b를 연산하기 위해서 b변수를 eax레지스터에 저장
00411CE8  add         eax,1 -> eax과 1을 더해서 eax레지스터에 저장
00411CEB  mov         dword ptr [b],eax -> eax를 b변수에 다시 저장.. 여기서 b변수의 값은 4
00411CEE  mov         ecx,dword ptr [b] -> 두번째 ++b를 연산하기 위해서 다시 b변수값을 ecx레지스터에 저장
00411CF1  add         ecx,1  -> ecx과 1을 더해서 ecx레지스터에 저장
00411CF4  mov         dword ptr [b],ecx -> ecx를 b변수에 다시 저장.. 여기서 b변수의 값은 5
00411CF7  mov         edx,dword ptr [b] -> + 연산을 위해서 b변수의 값을 edx레지스터에 저장
00411CFA  add         edx,dword ptr [b] -> edx 레지스터의 값과 b변수의 값을 합해서 edx레지스터에 저장
00411CFD  mov         dword ptr [a],edx -> edx레지스터의 값을 a변수에 저장

공부하시는거라면 모르겠지만 실제로 돌아가는 프로그램에서 저렇게 머리아프게 코드 짜시면 안됩니다. ;)
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

hyangil의 이미지

b가 3일때, 아래와 같이 계산하면 몇이 나올까요?

++b + ++b + ++b

이전 답글에 의하면, 6+6+6 = 18 이 나올꺼라 예상되지만, 실제 결과 값은 16이 나옵니다.

왜 이런것일 까요?

ㅠㅜ

나는 본인이 맞음을 증명하노라 ㅋ

chadr의 이미지

이것도 대략 이런식입니다..

((++b) + (++b)) + (++b))

b가 3이었으므로

(++b) + (++b)) -> 10.. b는 5

(10 + ++b) -> 16

이해 가시는지요?

5 + 5 + 6 -> 16

연산자 결합방향으로 이항연산자인 +가 평가될려면 우선 양 항이 먼저 평가 되어야합니다.
그렇기 때문에 첫번째 +가 평가되기 위해서는 양쪽 ++b가 평가되어서 5+5가 됩니다.
그리고 이 결과가 다시 두번째 +와 결합하여 평가되어야하기 때문에 양 항이 평가되어서
왼쪽항인 10은 상수이므로 아무런 일이 일어나지 않지만 오른쪽항인 ++b는 6으로 평가되어서 최종적으로
10+6이 됩니다.

여기까지 위의 결과를 내는 컴파일러 입장에서 분석을 한 것이지.. 다른 컴파일러에서는 실제로 이렇게 일어나지 않을수도 있습니다.

10*10 + 11*11 + 12*12가
(10*10) + (11*11) + (12*12)와 같이 평가 되어야하는 것 처럼

++연산자도 +연산자보다 우선순위가 높으므로

(++b) + (++b) + (++b)가 맞습니다만..

평가되는 변수 자체의 값이 변하는 경우에는 논리적으로 연산자 우선순위에 따라서 평가를 하더라도
중간에 값이 변해버리기 때문에 어떻게 평가될지는 모릅니다.

그러므로 저런 코드는 절~~대 만들지 마시고 정확히 써주셔야합니다.:)
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

익명 사용자의 이미지

어렵게 떠들자면 두 시퀸스 포인트 사이에서 동일한 객체가 두번이상 수정되는 행위는 정의되지 않은 행동 어쩌고 저쩌고가 되겠고, 걍 간단하게 말하자면 저런거 쓰지 마세요.

9가 나오던 10이 나오던 8이 나오던 컴파일러 맘입니다.

위와 같은 수식에서
1) 언제 b의 값을 읽어오는가
2) 언제 b의 값을 증가시키는가
이 두가지 행동을 어떤 순서대로 할지에 대해서, C언어는 특별히 제한을 두고 있지 않기 때문에 각자 컴파일러 하기 나름입니다. 보장된 것은 오로지 수식 마지막의 ;이전에 그 작업들이 모두 끝난다는 것 뿐. b의 증가를 단일 명령어로 하는가 레지스터로 읽어오고 증가시킨뒤 다시 쓰고 하는가에 따라서는 ;이후의 b의 값이 5가 아니라 4가 될 수도 있는 일입니다.

익명 사용자의 이미지

덧붙이자면, 위의 수식은 이식성이 없는 코드일 뿐만 아니라 근본적으로 틀린 코드입니다.

hyangil의 이미지

대충 무슨 말씀을 하시는지 감이 오네요

답변 감사합니다.

나는 본인이 맞음을 증명하노라 ㅋ

나는 본인이 맞음을 증명하노라 ㅋ

댓글 달기

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