[QUIZ] ++ 연산자 관련...

kuaaan의 이미지

#include <kldp.h>
int main()
{
   int i = 0;
   printf(" %d %d %d\n", i++, i++, i++);
}

퀴즈입니다.
위의 코드를 실행한 결과가 어떻게 될까요?

방금전에 돌려보고서 깜짝 놀랐습니다.
곰곰히 생각해보니 왜그런지 이해는 가는것 같기도 하고... ^^;;

※ Visual Studio에서 컴파일한 경우와 gcc 에서 컴파일한 경우가
결과가 틀린것 같습니다.

익명 사용자의 이미지

gcc로 돌려보니 "warning: operation on `i' may be undefined" 라는데요...

송효진의 이미지

test.c:1:19: kldp.h: 그런 파일이나 디렉토리가 없음 이게 정답 맞죠? :lol: :lol: :lol:

송효진의 이미지

본의 아니게 델파이를 좀 보게 되었는데요,
델파이와 VC++ 의 인자순서(?)가 틀리다는 설명이 있는것 같더군요.
델파이에서는 func(3,2,1) 순서로 인자를 배열하고,
VC++ 에서는 func(1,2,3) 순서로 인자를 배열한다는 설명이었던것 같습니다.
gcc도 func(3,2,1) 인가봐요?
귀찮다고 계산식을 그냥 써 넣으면 더 귀찮은 일이 발생할 확률이 많이 높겠네요.

얼른 c 를 배워야 하는데... :oops:

M.W.Park의 이미지

아련한 기억이지만, K&R에선 예로드신 방식의 코드는 쓰지말라고 나와있습니다.
여기 게시판에서도 비슷한 주제가 나온적이 있었고요.
컴파일러의 구현(기본 calling convention)이나 컴파일러 지시자에 따라 결과가 달랐던것으로 기억합니다.

비슷한 예로... 이런 수식이 어떻게 평가될까요?
i=i+++++i;

c/c++은 손 땐지가 아주 오래라... 8)

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

ole2000의 이미지

퀴즈를 낸사람의 정확한 의도가 뭔지 모르겠지만..

단지 증감연산자의 이해와 추가로 printf 함수에 대한 이해를 위한거라면

답이 2 1 0 이 되야 하지 않을까요?

Be cool...

shockyhan의 이미지

송효진 wrote:
본의 아니게 델파이를 좀 보게 되었는데요,
델파이와 VC++ 의 인자순서(?)가 틀리다는 설명이 있는것 같더군요.
델파이에서는 func(3,2,1) 순서로 인자를 배열하고,
VC++ 에서는 func(1,2,3) 순서로 인자를 배열한다는 설명이었던것 같습니다.
gcc도 func(3,2,1) 인가봐요?
귀찮다고 계산식을 그냥 써 넣으면 더 귀찮은 일이 발생할 확률이 많이 높겠네요.

얼른 c 를 배워야 하는데... :oops:


오해가 있을 듯 해서 부연하자면 인자순서가 다르다는 것이 아니고, 델파이와 C의 calling convension이 다르다는 뜻입니다. 바꾸어 말하면 실행 순간에 함수에 인자를 전달할 때 스택에 위치하는 인자의 순서가 다르다는 겁니다. 가령 델파이로 작성하는 프로그램에서 VC로 작성한 DLL을 호출할 경우 인자를 주고 받는 순서를 서로 다르게 예상하므로 오류가 발생합습니다. 해결 방법은 델파이나 VC 모두 calling convension을 지정하는 방법을 제공하므로 소스코드에서 명시적으로 calling convension을 맞춰주면 됩니다. VC는 __declspec(), 델파이는 함수 선언부 뒤에 cdecl; 이나 stdcall; 등을 추가해서 해결합니다.

===========================================================================
Shocky Han
BIM Consultant, Certified Information Systems Auditor
Seoul, Korea.
===========================================================================

죠커의 이미지

kuaaan wrote:
#include <kldp.h>
int main()
{
   int i = 0;
   printf(" %d %d %d\n", i++, i++, i++);
}

퀴즈입니다.
위의 코드를 실행한 결과가 어떻게 될까요?

방금전에 돌려보고서 깜짝 놀랐습니다.
곰곰히 생각해보니 왜그런지 이해는 가는것 같기도 하고... ^^;;

※ Visual Studio에서 컴파일한 경우와 gcc 에서 컴파일한 경우가
결과가 틀린것 같습니다.

검색을 해보시면 비슷한 글들을 볼 수 있을 것입니다. 이런 코드는 결코 쓰셔선 안된다고 생각합니다.

kuaaan의 이미지

1. gcc on linux 의 실행결과.

[root@fedora a]# ./a.out
 2 1 0

2. Visual Studio의 실행결과.

 0 0 0
Press any key to continue

냐하하... :)

CN 님의 말씀에 동의합니다.
이건 그냥 호기심에 해본 테스트였습니다....

근데... linux에서의 실행결과보다...
Visual Studio에서의 실행결과가 더 놀랍네요...

----------------------------------------------
한번뿐인 인생....
미친듯이 살아보자!
----------------------------------------------

pool007의 이미지

undefined 입니다. 답이 뭐가 나와도 correct죠.

--
Passion is like genius; a miracle.

eminency의 이미지

pool007 wrote:
undefined 입니다. 답이 뭐가 나와도 correct죠.

0이 출력되지 않으면 correct는 아니죠 -_-

딴지는 아닙니다만 그냥...

노루가 사냥꾼의 손에서 벗어나는 것 같이, 새가 그물치는 자의 손에서 벗어나는 것 같이 스스로 구원하라 -잠언 6:5

kslee80의 이미지

undefined 라면 어떤 결과가 나오던 간에
correct 하다고 이야기 할 수 없는게 아니던가요...

implementation defined 여야지 어떤 결과가 나오던 간에 correct 로 알고 있습니다.
(implementation defined 는 구현체에 그 결과를 위임한 것이니 말이죠)

cronex의 이미지

결론은 "그때그때 달라요~"
컴파일러를 뭘 썼느냐에 따라 다른거죠 -_-;;
저 부분은 컴파일러 구현에 따라 다른 것이니...

------------------------------------------------------------
이 멍청이~! 나한테 이길 수 있다고 생각했었냐~?
광란의 귀공자 데코스 와이즈멜 님이라구~!

죠커의 이미지

unspecifed이면 특정환경에서 결과를 이해하는 것은 도움이 되지만 undefined는 이런 것은 하지 않아야 한다만 기억 해두시는게 정신건강에 이롭습니다.

pool007의 이미지

kldp내에서 예전에도 나왔던 내용인 거 같은데요.

i++ + i++은 undefined입니다. unspecified가 아니라요.

Quote:

Except where noted, the order of evaluation of operands of individual
operators and subexpressions of individual expressions, and the order
in which side effects take place, is unspecified. Between the previous
and next sequence point a scalar object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore,
the prior value shall be accessed only to determine the value to be
stored. The requirements of this paragraph shall be met for each
allowable ordering of the subexpressions of a full expression;
otherwise the behavior is undefined.

스탠다드에서 정의를 해버리지 않으면 모두가 동의할 수 있는 correct를 찾을수란 없죠.

정말 직관에 따라 correct한 machine은 i++ 2개를 parallel 하게 수행해야합니다. 또, 앞서 인용문에서 unspecified 로 되어있는 경우를 생각해보죠. i++ + j++ 에서 i가 먼저 증가할까 j가 먼저 증가할까의 문제가 등장하고 이를 표준은 unspeicifed로 합니다. 이것이 정의 될 수 없는 이유는 2개의 서로 다른 메모리라고 해도 동시에 read/write가 되야 말이 되는데, 그것이 구현상 불가능하기 때문입니다.

CN님이 얘기하신대로 이런 코드는 써서는 안된다는게 정답일듯...

사족으로

Quote:

undefined 라면 어떤 결과가 나오던 간에
correct 하다고 이야기 할 수 없는게 아니던가요...

implementation defined 여야지 어떤 결과가 나오던 간에 correct 로 알고 있습니다.
(implementation defined 는 구현체에 그 결과를 위임한 것이니 말이죠)

이건 저도 잘 모르겠습니다...ㅠㅠ undefined는 "표준은 아무것도 이에 대해 요구하는 바가 없다" 입니다. 그리고 하지 말란일이고요. VC++의 결과는 황당하긴 한데, VC++이 잘못했다고 책임질 이유는 없을 듯하고요.. 말씀하신대로 "어떤결과가 나오더라도 correct하다고 말할 수 없다"는 말씀이 맞는듯..

--
Passion is like genius; a miracle.

ero의 이미지

오싱기해~ㅋ

댓글 달기

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