Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

이해가 안가는 코드....이런 현상이??

0 views
Skip to first unread message

Min,Lee

unread,
Jun 16, 2003, 5:06:31 PM6/16/03
to
Heap이라는 클래스를 하나 만들었는데요... heap sorting하려고요...
그런데 main에서...

void main()
{
Heap mine(5);

int a=3,b=8,c=4,d=1,e=9;

mine.add(&a);
mine.add(&b);
mine.add(&c);
mine.add(&d);
mine.add(&e);

mine.print();

cout << *mine.get() << *mine.get() << *mine.get() << *mine.get() <<
*mine.get() << endl;

/* cout << *mine.get();
cout << *mine.get();
cout << *mine.get();
cout << *mine.get();
cout << *mine.get();
cout << endl; */
}

이걸 실행하면
13489 가 나옵니다. 힙소팅이 되었으니까요... 그런데, 여기서 cout << .. << ..
<<.. 이걸 지우고, 밑에있는

cout << ;
cout << ;
.
.

이것으로 대체하면...
98431이라고 나옵니다.. 그러니까 순서가 뒤바뀝니다! -_-;; 한것이라고는 cout
<< << << 이걸 풀어준것밖에 없는데...
도저히 이해가 안갑니다.. C++을 모르는것도 아니고..-_-;;
심지어 ((cout << *mine.get()) << *mine.get()) << *mine.get() << *mine.get()
<< *mine.get() << endl;
이렇게 괄호를 일일이 쳐줘도 역시 마찬가지입니다...
하도 희안해서 printf 로 바꿔봤는데 같은 현상이더군요!! -_-;


Heap mine(5);

int a=3,b=8,c=4,d=1,e=9;

mine.add(&a);
mine.add(&b);
mine.add(&c);
mine.add(&d);
mine.add(&e);

mine.print();

// cout << *mine.get() << *mine.get() << *mine.get() << *mine.get() <<
*mine.get() << endl;
printf("%d", *mine.get() );
printf("%d", *mine.get() );
printf("%d", *mine.get() );
printf("%d", *mine.get() );
printf("%d", *mine.get() );

이 경우에는 98431이 나오고... 프린트하는 부분을...

printf("%d%d%d%d%d\n", *mine.get(), *mine.get(), *mine.get(), *mine.get(),
*mine.get() );
이렇게 바꿔주면...
13489로 나옵니다!!!

제가 뭘 모르고 있는것인가요??
MS VC++ 6 에서 해봤는데 이러길래, Linux에서 gcc로 돌려봤는데도.. 같은
현상입니다..-_-;;
환장하겠읍니다.. 아침이 밝아오는군요.. -_-;

Heap부분은 이상이 없어보이는데요.. 혹시나 해서 올려봅니다... 좀 길지만..-_-;
코드가 ugly합니다..

typedef int *node;


class Heap {
node *heap; // 힙을 위한 배열
int heap_size; // 현재 마지막 원소의 index라할수 있다. n까지 가능.
int n;

public:

Heap(int n) {
this->n = n;
heap_size = 0;
heap = new node[n+1];
}
~Heap() { delete[] heap; }

// 힙에 삽입한다.
void add(node p) {
int t;
node temp;


if (heap_size==n) {
cout << "Full heap! something wrong."; return;
}
heap[++heap_size] = p; // 마지막에 원소를 넣고

// move up! root쪽으로 올린다.
t = heap_size;

if (t==1) return;

while( *heap[t] > *heap[t/2] ) {
temp = heap[t];
heap[t] = heap[t/2];
heap[t/2] = temp;
t /= 2;
if (t==1) break;
}

}

// 힙에서 꺼냄.
node get(void) {
node result = heap[1], temp;
if (heap_size == 0) return 0;
heap[1] = heap[heap_size--]; // 마지막 원소를 root로 놓고

// move down! 아래쪽으로 내려간다.
int t = 1;

while(1) {
if (t*2 > heap_size) break; // leaf면 탈출
if (t*2+1 > heap_size) { // left child만 있다면
if (*heap[t] < *heap[heap_size]) { // 그 left가 자신보다 크면
temp = heap[t];
heap[t] = heap[heap_size];
heap[heap_size] = temp;
t *= 2;
} else break;
} else { // left,right 둘다 있고,
if (*heap[t*2] > *heap[t*2+1]) { // left가 right보다 크면
if (*heap[t] < *heap[t*2]) {
temp = heap[t];
heap[t] = heap[t*2];
heap[t*2] = temp;
t *= 2;
} else break;
} else { // right가 더 크면
if (*heap[t] < *heap[t*2+1]) {
temp = heap[t];
heap[t] = heap[t*2+1];
heap[t*2+1] = temp;
t *= 2; t++;
} else break;
}
}
}

return result;
}

// 힙을 출력.. 디버깅용..
void print(void) {
int i;

if (heap_size == 0) cout << "Empty!\n";
else {
for(i=1;i<=heap_size;i++)
cout << "(" << i << ":" << *heap[i] << ") ";
cout << "\n";
}
}
};


김승범

unread,
Jun 16, 2003, 10:21:14 PM6/16/03
to
"Min,Lee" wrote:
>
> Heap이라는 클래스를 하나 만들었는데요... heap sorting하려고요...
> 그런데 main에서...
>
> void main()

main() 함수는 int를 돌려주도록 선언하시는 것이 좋습니다.
그것이 표준에 의해서 보장되는 방식입니다.

> cout << *mine.get() << *mine.get() << *mine.get() << *mine.get() <<
> *mine.get() << endl;

> 심지어 ((cout << *mine.get()) << *mine.get()) << *mine.get() << *mine.get()


> << *mine.get() << endl;
> 이렇게 괄호를 일일이 쳐줘도 역시 마찬가지입니다...

mine.get()은 호출할 때마다 차례로 다른 값을 돌려주도록 설계가 된
함수인 것으로 보입니다. 그런데 위와 같이 하나의 문장으로 출력을 하면,
여러 번의 mine.get() 호출 중 어느 것이 먼저 평가될지 알 수 없습니다.

가장 단순하게 얘기해서,

y = f() + g();

위와 같은 식에서 f()가 먼저 평가될지 g()가 먼저 평가될지는 컴파일러의
마음이라고 정해져 있다는 것입니다. (여기서의 평가는 곧 함수 호출을
의미합니다.)

y = (f() + g()) + h(); // ⓐ
y = f() + (g() + h());

위와 같이 괄호를 사용하는 것도 식의 결합에는 영향을 미치지만 각각의
식이 어떤 순서로 평가될지에는 전혀 영향을 끼치지 못합니다. (이것이
많은 분들이 착각하시는 부분입니다. 결합 순서와 평가 순서는 서로
영향을 끼치지 않는 별개의 개념입니다. ⓐ에서 g()와 h()를 먼저 평가하고
마지막에 f()를 평가한 다음에 f()와 g()의 덧셈을 먼저 수행할 수도
있는 것입니다.)

하지만

cout << "Enter your name: "; // ⓐ
cin >> name; // ⓑ

이와 같은 코드에서 ⓐ가 먼저 평가될지 ⓑ가 먼저 평가될지조차 컴파일러
마음이라면 원하는 동작을 하는 프로그램을 만들기가 참으로 힘들겠지요. :)
그래서 모든 부작용(단순히 말해 함수 호출 등)이 넘어가지 못하고 반드시
어느 시점 전까지는 완료되어야 한다는 점들이 정의되어 있는데, 이를
시퀀스 포인트(sequence point)라 합니다. 문장을 구분하는 세미콜론에는
시퀀스 포인트가 존재하기 때문에 ⓐ의 부작용은 ⓑ의 부작용 전에 반드시
일어나야 한다는 조건이 생기게 됩니다.

시퀀스 포인트가 존재하는 곳에 대한 자세한 설명은 아래 글에서 참조하세요.
http://groups.google.co.kr/groups?selm=3DB97B90.82FF374B%40bawi.org

그리고 다음 글도 (비록 영문이지만) 많은 도움이 되기를 바랍니다.
http://groups.google.co.kr/groups?selm=3E02D596.9E4E11ED%40bawi.org

--
김승범

Chong-Dae Park

unread,
Jun 16, 2003, 10:59:28 PM6/16/03
to
Min,Lee <abra...@nownuri.net> wrote:
> Heap이라는 클래스를 하나 만들었는데요... heap sorting하려고요...
> 그런데 main에서...
>
> 이걸 실행하면
> 13489 가 나옵니다. 힙소팅이 되었으니까요... 그런데, 여기서 cout << .. << ..
> <<.. 이걸 지우고, 밑에있는
>
> cout << ;
> cout << ;
> .
> .
>
> 이것으로 대체하면...
> 98431이라고 나옵니다.. 그러니까 순서가 뒤바뀝니다! -_-;; 한것이라고는 cout
> << << << 이걸 풀어준것밖에 없는데...
> 도저히 이해가 안갑니다.. C++을 모르는것도 아니고..-_-;;

98341 순으로 나오는 게 정상입니다. Max heap을 만드셨으니깐요.

> 심지어 ((cout << *mine.get()) << *mine.get()) << *mine.get() << *mine.get()
> << *mine.get() << endl;
> 이렇게 괄호를 일일이 쳐줘도 역시 마찬가지입니다...
> 하도 희안해서 printf 로 바꿔봤는데 같은 현상이더군요!! -_-;

#include <iostream>

int main()
{
using namespace std;
int i=0;
cout << i++ << i++ << i++ << endl;
}


어떤 결과가 나올 지 예상되나요? :)

--
박종대
--
"I am a HAL 9000 computer, Production Number 3. I became operational
at the HAL Plant in Urbana, Illinois on January 12, 1997."
- spoken by HAL in the book 2001: A Space Odyssey, Arthur C. Clarke

Min,Lee

unread,
Jun 17, 2003, 9:36:47 AM6/17/03
to
아... 감사합니다! sequence point라니.. 그런것이 있었군요..
정말이지 항상 뭔가 좀 알거 같은 느낌일때 이런 뒤통수 후려침은
저로하여금 함부로 떠들지 못하게 만드는군요.. -_-;;
감사합니다. 귀중한 정보를 얻었읍니다. 계속 미뤄놓고 있지만,
표준을 정말 한번 공부해봐야겠다는 생각이 드는군요...
김승범님과 박종대님은 뉴스그룹에서 오랫동안 봐와서 이름이 참 낯익습니다. ^^;
항상 좋은글을 올려주셔서 큰 도움을 받고 있읍니다..
그런데, 질문이 생겼읍니다..
평가순위와 결합순위가 무관하고 sequence point에 대한 개념도 이해한것
같습니다.
그러나 cout << 은 cout의 method를 호출하는 함수호출아닙니까?
cout.operator<<(a).operator<<(b).operator<<(c); 라고 볼수 있다면,
그렇다면 자료에서 보듯 the call to a function, after the arguments have been
evaluated..
에 해당하는거 아닌가요? 즉, 함수콜이므로 sequence point가 있는거 아닌지요??
함수콜이 연속해서 일어나는 상황에서 각 함수콜들 사이에 sequence point가
있는것이
당연할 것으로 생각이 되거든요?? (그렇지 않기때문에 제가 이런 경우를
당하게되는거 같네요)

혹시 이게 C의 spec이기때문에 C++에선 다르기때문에 이 생각이 틀린거라면,
그럼 C++에서는 cout과 같이 referenc의 return으로 메소드가 연이어 호출될때는
sequence point가 마지막 ; 에 있다는 얘기인가요?
즉, 이전 C의 'the call to a function, after the arguments have been
evaluated..'는
고쳐진것인가요...
(아마 효율성을 위해? parameter들을 한꺼번에 모두 평가한다?? - 추측..)

박종대님이 들어주신 예인
int i=0;
cout << i++ << i++ << i++; 의 결과는 VC++에서 210이네요..
역시 뒤에서부터 평가가...(충격이군요-_-;;)
이건 C++에서 함수콜시점에서도 sequence point가 없다는 제 추측을 증명하는것
아닌지..

좋은 자료 감사합니다. 많이 배웠읍니다. 스스로 더 공부해보도록
하겠읍니다..흠..

Lee, Sin-jae.

unread,
Jun 17, 2003, 10:59:34 AM6/17/03
to
Min,Lee wrote:
> cout.operator<<(a).operator<<(b).operator<<(c); 라고 볼수 있다면,

아닙니다. overator<<() 는 맴버가 아닌 함수입니다. 아래에서 얘기를 하겠습
니다.

> 박종대님이 들어주신 예인
> int i=0;
> cout << i++ << i++ << i++; 의 결과는 VC++에서 210이네요..
> 역시 뒤에서부터 평가가...(충격이군요-_-;;)
> 이건 C++에서 함수콜시점에서도 sequence point가 없다는 제 추측을 증명하는것
> 아닌지..

cout << i++ << i++ << i++; 는 다음 코드와 동일합니다.

operator<<(operator<<(operator<<(cout, i++), i++), i++);
(참고로 i++의 순서는 위의 코드 그대로입니다)

일단 바깥쪽부터 해석해 나가자면

operator<<(###, i++);

여기에서 ###와 i+++ 중 어느 쪽부터 먼저 해석해야 하는지는 표준에 정의되
어 있지 않습니다. (함수의 인자들의 평가 순서는 정의되어 있지 않습니다)
왼쪽 먼저일수도 있고, 오른쪽 먼저일수도 있고, 불규칙하게 결정될 수도 있
습니다. 이런 이유로, 세개의 i++ 중에서 어떤 것을 먼저 평가해야 하는지 알
수가 없습니다.

VC++에서 결과가 210이었다고 해도 그것이 모든 C++ 컴파일러에서 동일하게
작동한다고는 볼 수 없으며, 설사 Visual C++ 만 사용한다고 하더라도 저런
것에 의존하는 프로그래밍을 하는 것은 대단히 위험한 방식입니다.

--
Lee, Sin-jae.
E-mail: lsj0713 at yahoo dot co dot kr

김승범

unread,
Jun 17, 2003, 12:56:52 PM6/17/03
to
"Min,Lee" wrote:
>
> 아... 감사합니다! sequence point라니.. 그런것이 있었군요..
> 정말이지 항상 뭔가 좀 알거 같은 느낌일때 이런 뒤통수 후려침은
> 저로하여금 함부로 떠들지 못하게 만드는군요.. -_-;;

그런 순간들을 겪을 때마다 새로운 것을 공부하는 맛이 나지 않습니까? :-)

> 감사합니다. 귀중한 정보를 얻었읍니다. 계속 미뤄놓고 있지만,
> 표준을 정말 한번 공부해봐야겠다는 생각이 드는군요...

그런데 저도 표준을 필요할 때마다 참조는 하지만, 표준을 교과서 보듯
차근차근 공부해본 적은 없습니다. 워낙 양이 방대해서 웬만큼 시간과
노력을 들이지 않으면 안 될 것 같더군요..

> 그러나 cout << 은 cout의 method를 호출하는 함수호출아닙니까?

오른쪽에 오는 식의 형에 따라서 다릅니다.
멤버 함수를 호출하게 되는 경우는 std::basic_ostream<>의 클래스 정의에
멤버 함수 operator<< 가 나열된 경우로 한정되어 있습니다.
bool, {signed, unsigned} {short, int, long}, float, double, long double,
const void*, basic_streambuf<>*, 몇 가지 함수 포인터의 경우입니다.

> cout.operator<<(a).operator<<(b).operator<<(c); 라고 볼수 있다면,

이 가정이 참이라고 이후 논의를 진행해 나가도록 하죠.

> 그렇다면 자료에서 보듯 the call to a function, after the arguments have been evaluated..
> 에 해당하는거 아닌가요? 즉, 함수콜이므로 sequence point가 있는거 아닌지요??
> 함수콜이 연속해서 일어나는 상황에서 각 함수콜들 사이에 sequence point가 있는것이
> 당연할 것으로 생각이 되거든요?? (그렇지 않기때문에 제가 이런 경우를
> 당하게되는거 같네요)

말씀하신 부분은, 함수의 인자가 평가된 후 실제로 함수가 호출되는 시점에
시퀀스 포인트가 존재한다는 뜻입니다. 즉 함수가 호출되기 전에 함수의
인자의 평가가 끝마쳐져야 한다는 것이지요. 따지고 보면 당연한 얘기지요?
인자가 뭔지도 모르고 함수 호출을 할 수는 없으니까.. :)

그리고 전에 소개해 드린 글은 C 그룹에 올린 것이라 C 표준에 있는 시퀀스
포인트를 설명하고 있는데, C++ 표준에서는 여기에 덧붙여서 함수의 반환값이
복사되고 나서 함수 밖에 있는 어떠한 식도 실행되기 전에 시퀀스 포인트가
존재하도록 규정하고 있습니다(1.9/17).

그리고 함수 호출식은 후위식(postfix expression)과 인자식 목록(argument
expression list)으로 구성되는데, 이들 사이의 평가 순서는 정해져 있지
않습니다(unspecified)(5.2.2/8). 저도 확실치는 않습니다만, 이는 F(A, B)
에서 F가 먼저 평가되고 나중에 A와 B가 평가될지, 반대로 A와 B가 먼저
평가되고 나중에 F가 평가될지 정해져 있지 않다는 것으로 생각됩니다.
물론 어느 경우에도 A와 B 사이의 평가 순서는 정해져 있지 않은 것이고요.

즉 cout.operator<<(a).operator<<(b); 은 다음과 같은 식으로 수행될 수
있다는 것으로 해석됩니다. (저도 확실치는 않네요.)

[경우 1] 후위식이 일관되게 먼저 평가되는 경우
cout.operator<<(a).operator<<(b) 평가 ≡T
(cout.operator<<)(a).operator<< 평가 ≡G
cout.operator<< 평가 ≡F
a 평가 ≡A
시퀀스 포인트
F(A) 호출 ≡R
시퀀스 포인트
R.operator<< 평가 ≡G
b 평가 ≡B
시퀀스 포인트
G(B) 호출 ≡T
시퀀스 포인트

[경우 2] 인자식이 일관되게 먼저 평가되는 경우
cout.operator<<(a).operator<<(b) 평가 ≡T
b 평가 ≡B
시퀀스 포인트
(cout.operator<<)(a).operator<< 평가 ≡G
a 평가 ≡A
시퀀스 포인트
cout.operator<< 평가 ≡F
F(A) 호출 ≡R
시퀀스 포인트
R.operator<< 평가 ≡G
G(B) 호출 ≡T
시퀀스 포인트

물론 다른 경우도 가능합니다만, 대표로 두 가지의 예를 들어 봤습니다.
보기가 쉽지 않으실 텐데, 평가의 결과값을 X라 칭하는 것을 '≡X'라고
나타냈습니다. 한참을 끙끙대서 풀었는데 맞는지 모르겠네요.

위 두 가지 경우만 보더라도, a와 b의 평가 순서가 서로 다른 것을
보실 수 있습니다. 저렇게 시퀀스 포인트에 겹겹이 둘러싸여 있더라도,
근본적으로 F(A)에서 F가 먼저 평가되느냐 A가 먼저 평가되느냐의 차이에
의해서 결과가 달라질 수 있는 것입니다.

>
> 혹시 이게 C의 spec이기때문에 C++에선 다르기때문에 이 생각이 틀린거라면,
> 그럼 C++에서는 cout과 같이 referenc의 return으로 메소드가 연이어 호출될때는
> sequence point가 마지막 ; 에 있다는 얘기인가요?
> 즉, 이전 C의 'the call to a function, after the arguments have been
> evaluated..'는
> 고쳐진것인가요...
> (아마 효율성을 위해? parameter들을 한꺼번에 모두 평가한다?? - 추측..)

앞서 자세히 말씀드렸듯이, 그런 것은 아닙니다.

>
> 좋은 자료 감사합니다. 많이 배웠읍니다. 스스로 더 공부해보도록
> 하겠읍니다..흠..

많은 발전 있으시길 바랍니다. 이 그룹에서도 많이 나눠주시고요. :)

--
김승범

김승범

unread,
Jun 17, 2003, 1:00:26 PM6/17/03
to
"Lee, Sin-jae." wrote:
>
> Min,Lee wrote:
> > cout.operator<<(a).operator<<(b).operator<<(c); 라고 볼수 있다면,
>
> 아닙니다. overator<<() 는 맴버가 아닌 함수입니다. 아래에서 얘기를 하겠습
> 니다.

a, b, c의 형에 따라 다르지 않습니까?

>
> cout << i++ << i++ << i++; 는 다음 코드와 동일합니다.
>
> operator<<(operator<<(operator<<(cout, i++), i++), i++);
> (참고로 i++의 순서는 위의 코드 그대로입니다)

i가 int라면, basic_ostream::operator<<(int)라는 멤버가 존재하는데
이 멤버 함수를 이용해야 하는 것 아닐까요..?

--
김승범

Lee, Sin-jae.

unread,
Jun 17, 2003, 3:21:33 PM6/17/03
to

네 제가 잘못 알고 있었습니다. 제가 가진 C++ 책에는 << 연산자의 오버로딩
은 다음과 같이 이루어진다고 쓰여 있었습니다.

ostream& operator<<(ostream &os, Type &T);

그래서, 내장형(int와 같은)도 당연히 같은 방법으로 되어 있으리라 생각했는
데 한방 먹은 것 같습니다-_-;;; 덧붙여 변명하자면 제가 본 책에서는 위와
같은 코드를 통해 설명하고 있는지라...-_-;;;

같은 << 연산자 오버로딩 함수인데도 한쪽은 cout.operator<<(Type T)로 작동
하고 다른 한쪽은 operator(cout, Type T)로 작동한다는 것이 재밌게 느껴지
는군요.

그리고 질문이 하나 있습니다. 다른 글타래에서 다음과 같이 적으셨는데요.

> 그리고 함수 호출식은 후위식(postfix expression)과 인자식 목록(argument
> expression list)으로 구성되는데, 이들 사이의 평가 순서는 정해져 있지
> 않습니다(unspecified)(5.2.2/8). 저도 확실치는 않습니다만, 이는 F(A, B)
> 에서 F가 먼저 평가되고 나중에 A와 B가 평가될지, 반대로 A와 B가 먼저
> 평가되고 나중에 F가 평가될지 정해져 있지 않다는 것으로 생각됩니다.
> 물론 어느 경우에도 A와 B 사이의 평가 순서는 정해져 있지 않은 것이고요.

func(int a, int b)

위에서 func가 후위식에 해당하고 (int a, int b)가 인자식 목록에 해당한다
고 이해하면 맞는 것입니까?

김승범

unread,
Jun 17, 2003, 7:53:38 PM6/17/03
to
"Lee, Sin-jae." wrote:
>
> 네 제가 잘못 알고 있었습니다. 제가 가진 C++ 책에는 << 연산자의 오버로딩
> 은 다음과 같이 이루어진다고 쓰여 있었습니다.
>
> ostream& operator<<(ostream &os, Type &T);
>
> 그래서, 내장형(int와 같은)도 당연히 같은 방법으로 되어 있으리라 생각했는
> 데 한방 먹은 것 같습니다-_-;;; 덧붙여 변명하자면 제가 본 책에서는 위와
> 같은 코드를 통해 설명하고 있는지라...-_-;;;

저런.. 무슨 책입니까? :-)

>
> func(int a, int b)
>
> 위에서 func가 후위식에 해당하고 (int a, int b)가 인자식 목록에 해당한다
> 고 이해하면 맞는 것입니까?

네. 정확히는 func가 후위식, int a, int b (괄호 없이)가 인자식 목록에
해당한다는 뜻으로 썼습니다.

--
김승범

Lee, Sin-jae.

unread,
Jun 17, 2003, 8:43:46 PM6/17/03
to
김승범 wrote:
>
> 저런.. 무슨 책입니까? :-)
>

한빛출판사의 "C 프로그래머를 위한 C++"이란 책입니다. 제가 C만 알고있던
시절 급하게 윈도우용 프로그램을 개발해야 되는 상황에 처했기 때문에, 얇은
책중에서 고르다보니...;;; 책이 나쁘다거나 잘못된 책은 아닌데, 다만 두께
가 얇다보니 빼먹고 지나가는 부분이 많더군요;;; (게다가 C++ 표준이 정립되
기 전에 쓰여진 것 같습니다;;;) 이래서 책은 두꺼워야 제맛인데... (제 책
선택법입니다. 무조건 두꺼운책...-_-;;)

Min,Lee

unread,
Jun 18, 2003, 1:26:48 PM6/18/03
to
> 그런 순간들을 겪을 때마다 새로운 것을 공부하는 맛이 나지 않습니까? :-)

그렇~~습니다~..(노무현 대통령님 어투) 바로 그것입니다.. -_-;;

김승범님이 올려주신 글들을 프린트해서 죙일 봤더니...
드디어 감이 오는것 같습니다. -_-;; 감사합니다.
아마 VC에서는 (2)번 경우처럼 평가가 되는것으로 '추측'이 되는군요.
한참을 끙끙대며 푸셨다는 식들을 보니 감동의 물결이~~ -_-;;
맞는것으로 생각됩니다.
다시 한번 감사드리면서.. 건강하시기 바랍니다..
다음번에 다시 뵙죠.. ^^;;

0 new messages