포인터에 대해, 어떤 책에서

cppig1995의 이미지

오늘 이런 표현을 읽었습니다.

Quote:
int * ptr이라고 선언했을 때, 'ptr'이라고 쓰면 int * [ptr]이므로 int * 형이고,
'*ptr'이라고 쓰면 int [* ptr]이므로 int 형이다.

꽤나 명쾌한데요. ^^
설마 이런 류의 표현을 저만 처음 접해본 건 아니겠죠?
(저만 혼자 촙5인가 봅니다. 흑흑)

익명사용자의 이미지

그런 이유로 C언어에서는 포인터변수를 선언할때 *연산자를 변수이름에 붙히는 관습(?)이 있죠.
int *ptr;

그러나 C++에서는 int* ptr;와 같이 자료형에다가 붙히는 것을 선호합니다.
이 이유는 다음분에게 pass.

cwryu의 이미지

그런 식이면 C++에서 int &ref 라고 선언했을 때 &ref가 int가 되겠네요. :P

두 경우는 C 신텍스에서도 다른 토큰이고, 위와 같은 설명은 논리적인 게 아니라 헷갈리는 사람들을 위한 암기법일 뿐이죠..

----
익명이나 오래전 글에 리플은 무조건 -1

익명사용자의 이미지

레퍼런스는 선언할 수 없지 않나요?

익명사용자의 이미지

C++은 C를 처음 디자인한 사람이 디자인한 언어가 아니죠.
기존의 C에다 자신(C++)의 다자인을 첨가한 것입니다.
그 첨가를 바탕으로 기존 C의 디자인까지 첨가된 디자인을 기준으로 판단하는 것은 이상합니다.

익명사용자의 이미지

TCPL에서도 그런 식으로 설명했던거 같네요. C에서의 표기법은 그런 식으로 이해하기 편하게 의도한 것일 수도..

wish의 이미지

윗분께서도 언급하셨지만,

The C Programming Language 포인터 설명 부분에서, 포인터 문법에 관해 설명할 떄 이런 방식으로 설명하고 있습니다.

TCPL 저자가 C 언어 저자 이므로 처음 프로그래밍 언어를 만들 때 그런 의도를 가지고 있었다고 저는 생각합니다.

말로 쓸라니 애매해서 그냥 인용 해 봅니다 ^^;

Quote:

The declaration of the pointer ip,

int *ip'

is intended as a mnemonic; it says that the expression *ip is an int. The sntax of the declaration for a variable mimics the syntax of expressions in which the varable might appear. The resoning applies to function declarations as well. For example,

double *dp, atof(char *);

says that in an expression *dp and atof(s) have values of type double, and taht the argument of atof is a pointer to char.

이거 보고 저는 C 만든 사람들이 저런식으로 만들었겠구나 해서 그 뒤로는 대부분의 선언을 저 바탕위에서 이해하고 있습니다.

int *a(void) // *a() 는 int 형, a() 는 int 형 포인터, a 는 함수
int (*a)(void) // (*a)() 는 int 형, *a 는 함수, a 는 함수 포인터

이런식으로 이해합니다. 머리가 나빠선지 저한테는 머리속에 안 들어와 박히더군요 ;;

익명사용자의 이미지

저것은 포인터 뿐아니라 배열에서도 마찬가지입니다.
int list[2][4];라고 했을때 list는 int[2][4]꼴이고 int list[2][4];
list[]는 int[4]꼴이 됩니다. int list[2][4];

int *ptr;에서 ptr는 int *꼴이고
int *ptr;에서 *ptr은 int꼴인 것처럼...

전웅의 이미지

같은 논리라면,

int *parr[10];

에서 *parr 이라고 쓰면 int [10] 이 남으니 배열이 되어야 겠군요!
(물론, 아니라는 얘깁니다!! --;)

C 언어의 선언은 기본적으로 수식내 사용되는 형태를 그대로 옮겨 구성
되어 있습니다. 흔히,

"A declarations mimics use."

로 널리 알려진 표현이 말하는 내용입니다. 덕분에 선언 해석시
포인터-배열 유도 혹은 포인터-함수 유도가 인접한 경우에는 연산자
우선순위에 따라 먼저 적용되는 type 유도를 파악할 수 있습니다.

보여주신 방법은 복잡한 선언을 풀어쓴 후에 가장 최종 유도된 type
부터 벗겨내는 과정에 불과합니다. 예로 든 경우를 보면,

- array of 10 pointers to int

에서 첫번째 유도가 array 이므로 parr 에 [n] 을 붙인 parr[n] 은

- pointer to int

즉, int * 가 됩니다. 이제 첫번째 유도가 pointer 이므로 parr[n]
에 * 를 붙인 *parr[n] 은

- int

가 됩니다. 하지만, 딱 여기까지만을 보여줄 뿐 배열이 포인터로
decay 한 후 포인터 연산이 적용될 경우의 결과를 보여주지는 못합니다.

어느 문맥에서 설명된 내용인지 모르겠지만 포인터 이해를 위한 방법
이라기 보다는 복잡한 선언을 풀어내기 위한 (다소 부족한) 방법에
불과합니다. 때문에 저는 선언에서 type 유도의 순서를 결정할 때
연산자 우선순위를 그대로 적용할 수 있다는 사실을 설명할 때에만
사용할 뿐 그 이외에는 영어식 표현으로 풀어쓰는 방식을 선호합니다.

C 언어에서 포인터 유도(pointer derivation)가 prefix 가 아닌 postfix
로 붙었다면 선언을 적고 이해할 때 보다 손쉬웠을 것입니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

음...

역시 같은 논리로,

선언과 사용을 대조해 보면,

int a[10];
a는 int[10], a 는 int 배열, 그런데 씨에서 배열을 지칭할 때 포인터를 사용하므로 pointer to int

int *parr[10];
*parr 는 int[10], *parr 는 int 배열, 똑같이 pointer to int
단 *parr[3] 은 int, parr[3] 은 pointer to int

중간 과정은 이상해도 결과는 대충 맞는듯 합니다만 :)

이게

array of 10 pointers to int 에서 배열의 첫번째 원소가 pointer to int 이고
a pointer to array of 10 int 에서 int 배열을 가르키는 포인터 또한 pointer to int 라서

이렇게 되는 게 아닌 가 싶습니다 ;;

int *parr[10] 은 선언이고
사용시의 *parr 은 결국 배열의 첫번째 원소를 가르키는 것이니 배열이라고 생각해도 크게 문제 없을 듯 하다고 조심스레 써 봅니다.

선언에서 [] 와 * 는 차이가 있지만, 사용할 때는 *나 [] 나 타입을 변화시키는 것은 똑같기 때문에 돼지님 식으로 해도 크게 문제가 없을 듯 합니다.

예를 들어

int ***a[10][10] 에서 **a 는 int *[][] 이므로 pointer to pointer to pointer to int 가 되겠죠~
굳이 다 풀어서 써보면 a 는 array of 10 arrays of 10 pointers to pointer to pointer to int 이므로,
a 는 배열
*a 는 a[0] 따라서 array of 10 arrays... 의 첫번째 원소,
**a 는 array of 10 arrays of 10 pointers... 의 첫번째 원소
결국 pointer to pointer to pointer to int 가 됩니다.

전웅의 이미지

> 선언과 사용을 대조해 보면,
>
> int a[10];
> a는 int[10], a 는 int 배열, 그런데 씨에서 배열을 지칭할 때 포인터를 사용하므로 pointer to int
>

배열을 수식 내에서 사용할 때 포인터로 변환된다고 해서 배열의 type
자체가 포인터인 것은 아닙니다.

> int *parr[10];
> *parr 는 int[10], *parr 는 int 배열, 똑같이 pointer to int
>

요즘 참 이상합니다. 제가 어떤 부분이 사실이 아니라고 느낌표까지 찍어
가며 글을 남겨도 바로 그 글 밑에 제가 말씀드린 사실과 정반대의 거짓을
사실인 것처럼 말씀하시는 분이 계시는군요. 제 글발이 다 해서 더 이상
설득력이 없는 건가요? 제가 썼던 글 다시 인용합니다.

제가 씀:
] 같은 논리라면,
]
] int *parr[10];
]
] 에서 *parr 이라고 쓰면 int [10] 이 남으니 배열이 되어야 겠군요!
] (물론, 아니라는 얘깁니다!! --;)

*parr 이 int 형 배열이라면, sizeof(*parr) 의 결과는 10 * sizeof(int)
가 나와야 하겠군요! 직접 해보시기 바랍니다. 님이 말씀하시는 (*parr 을
통해 포인터로 접근하게 되는) "배열"이 int [10] 이 말하는 그 "배열"이
아닙니다!

> 단 *parr[3] 은 int, parr[3] 은 pointer to int
>
> 중간 과정은 이상해도 결과는 대충 맞는듯 합니다만 :)
>

엄격한 정의와 해석을 적용해야 하는 경우에 "대충" 맞는 것은 "맞는" 것이
아닙니다. 아직은 프로그램 코드 대충 짜서 던져주면 컴파일러가 옳다구나
하면서 올바르게 이해해 주는 기술 수준이 되지는 못합니다.

*parr[3] 은 int 형에서 시작된 유도를 모두 벗겨낸 형태이므로 당연히
int 가 될 수 밖에 없고, parr[3] 은 가장 "마지막" 유도를 벗겨낸 형태
이므로 당연히 맞을 수 밖에 없습니다.

따라서 ("중간"에 이루어진 유도를 먼저 벗겨낼 수 없음에도 불구하고)
int *parr[10] 에서 *parr 만 떼어내면 진정 배열이 된다고 생각
하시는지요?

> 이게
>
> array of 10 pointers to int 에서 배열의 첫번째 원소가 pointer to int 이고
> a pointer to array of 10 int 에서 int 배열을 가르키는 포인터 또한 pointer to int 라서
> 이렇게 되는 게 아닌 가 싶습니다 ;;
>

대체 무슨 말씀을 하고 계신 것인지 정리가 되지 않습니다. 위에서 말씀
드렸듯이 이야기가 시작부터 잘못되어 있습니다. 시작점이 거짓인 논리가
결론이 참일 수는 없습니다.

>
> int *parr[10] 은 선언이고
> 사용시의 *parr 은 결국 배열의 첫번째 원소를 가르키는 것이니 배열이라고 생각해도 크게 문제 없을 듯 하다고 조심스레 써 봅니다.
>

parr 의 type 은 array of 10 pointers of int 입니다. 만약, 말씀하신
억지 논리로 *parr 이 int [10] 이라면 분명 sizeof(*parr) 은 int [10]
의 크기인 sizeof(int)*10 이 나와야 합니다. 크게 문제가 되지 않는지요?

int *parr[10] 이라는 선언은 int *(parr[10]) 로 해석되는 선언입니다 -
명칭에 보다 가깝게 붙어 있는 [10] 가 가장 마지막에 이루어지는 type
유도입니다. 논리가 이러한 유도의 순서를 무시할 수 있는 것이라면,

int (*func)(void);

에서 func() 의 결과는 int * 가 되어야 하는지요? 유사하게

int (*parr)[10];

에서 parr[n] 의 결과는 int * 가 되어야 하는지요?

>
> 선언에서 [] 와 * 는 차이가 있지만, 사용할 때는 *나 [] 나 타입을 변화시키는 것은 똑같기 때문에 돼지님 식으로 해도 크게 문제가 없을 듯 합니다.
>

위에서 질문 드린 부분에 대해서 고민해 보시기 바랍니다. 정말로 문제가
되지 않는다고 생각하시는지요?

선언은 type 을 명시합니다. 배열을 사용할 때 type 이 포인터로
변환된다고 해서 모든 경우에 시작부터 포인터로 존재하는 것은 아닙니다.
sizeof 연산자는 배열이 포인터로 변환되는 것을 막고 원래 type 그대로를
확인할 수 있는 기회를 주기 때문에 그 차이를 분명하게 보일 수 있습니다.

>
> 예를 들어
>
> int ***a[10][10] 에서 **a 는 int *[][] 이므로 pointer to pointer to pointer to int 가 되겠죠~
> 굳이 다 풀어서 써보면 a 는 array of 10 arrays of 10 pointers to pointer to pointer to int 이므로,
> a 는 배열
> *a 는 a[0] 따라서 array of 10 arrays... 의 첫번째 원소,
> **a 는 array of 10 arrays of 10 pointers... 의 첫번째 원소
> 결국 pointer to pointer to pointer to int 가 됩니다.
>

위에서 제가 말씀드린 논리를 적용하면 다 무너져 내리는 근거들입니다.
억지는 여기까지면 충분합니다 - 제 표현이 과격하다고 생각하지 마시기
바랍니다. 제 글을 조금만 더 주의를 기울여 읽어주셨다면 나오지 않았을
내용들입니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

전웅 님 말씀이 맞습니다. 쓸데 없는 댓글 붙여서 죄송합니다. 긴 댓글을 썼었는데, 필요 없는 것 같아서 지워 버렸습니다. 이것만 한 번 생각해 보시기 바랍니다. 제가 전웅님께서 쓰신 댓글의 내용을 "전혀" 모르고 쓴 글인지를... 제가 쓴 건 어 이렇게 대충해도 엄밀하게 한 거랑 비슷하게 끼워 맞출 수 있구나~ 신기하네~ 라는 느낌으로 쓴 글입니다. 그리고 *parr 의 sizeof 가 인트 배열 크기로 나올 것이다라고 생각할 정도로 "바보"는 아닙니다만 ;;;; 한가지 더, 제 댓글은 전웅님 글에 대한 반박이 아닙니다. 아니 될 수가 없습니다 ;;;

그리고 제가 전웅님 틀렸다고 꽥꽥 소리지른 것도 아닌데, 완전 글 쓰시는 것이 잘 모르는 초등학생 가르치듯이 쓰시는 군요. 잘못된 부분을 고치는 것이 목적이십니까? 공개 게시판에서 한 사람 망신 주실려고 쓰신 겁니까? 설령 제가 완전 억지를 부렸다고 하더라도 이런 식의 글쓰는 것은 적어도 공개 게시판 예의는 아닙니다. 좀 많이 당황스럽군요.

전웅의 이미지

> 전웅 님 말씀이 맞습니다. 쓸데 없는 댓글 붙여서 죄송합니다.

님의 댓글이 쓸데 없다는 의도가 아니었습니다 - 아래 이어서 말씀
드리겠습니다.

> 긴 댓글을 썼었는데, 필요 없는 것 같아서 지워 버렸습니다. 이것만
> 한 번 생각해 보시기 바랍니다. 제가 전웅님께서 쓰신 댓글의 내용을
> "전혀" 모르고 쓴 글인지를...

제가 님이 어느 정도 이해하고 계신지 판단할 수 있는 기준은 님이 작성해
올리신 글 뿐이 없습니다.

제가 "...는 사실이 아니다" 라는 주장과 함께 이를 설명하기 위한 근거를
남겼음에도 불구하고 "...가 사실인 것 같다" 라는 추측성 글을
남기셨으니, 제 입장에서는 님이 제 글을 전혀 보시지 않으셨거나, 혹은
보셨더라도 제대로 이해하지 못하셨거나 하는 두 가지 가능성 밖에 생각할
수 없습니다.

> 제가 쓴 건 어 이렇게 대충해도
> 엄밀하게 한 거랑 비슷하게 끼워 맞출 수 있구나~ 신기하네~ 라는
> 느낌으로 쓴 글입니다.

이 주제가 비록 자유 게시판에 올라와 있기는 하지만 내용이 진행된
흐름을 보면, 느낌만으로 추측성 답글을 남기기에는 부적절하다고
생각하지는 않으시는지 궁금합니다. (다양한 결론이 가능한 토론에
사용되는 것에는 아직도 반대하지만) 점수제가 사용되고 있어 기술적으로
잘못된 답변이 적절히 가려질 수 있는 점은 다행이지만, 잘못된 내용을
정확한 논리적 바탕도 없는 추측만으로 작성해 올리는 것이 무책임할 수
있다는 생각은 안 해보셨는지요?

> 그리고 *parr 의 sizeof 가 인트 배열 크기로
> 나올 것이다라고 생각할 정도로 "바보"는 아닙니다만 ;;;; 한가지 더,
> 제 댓글은 전웅님 글에 대한 반박이 아닙니다. 아니 될 수가
> 없습니다 ;;;
>

제 댓글에 대해 반박을 하고 안 하고의 문제가 아닙니다 - 제 댓글에 반박
을 했기 때문에 제가 직설적인 표현을 섞어 답변을 달았다고 판단하셨다면
오해이십니다. 문제는 어떤 내용이 어떤 형식으로 올라왔냐는 것입니다.

> 그리고 제가 전웅님 틀렸다고 꽥꽥 소리지른 것도 아닌데, 완전 글
> 쓰시는 것이 잘 모르는 초등학생 가르치듯이 쓰시는 군요. 잘못된
> 부분을 고치는 것이 목적이십니까? 공개 게시판에서 한 사람 망신
> 주실려고 쓰신 겁니까? 설령 제가 완전 억지를 부렸다고 하더라도
> 이런 식의 글쓰는 것은 적어도 공개 게시판 예의는 아닙니다. 좀 많이
> 당황스럽군요.

옳고 그름이 분명한 이야기를 나누는 문맥에서 추측을 바탕으로 한 주장을
통해 잘못된 내용을 전달하는 것 역시 공개 게시판에 대한 예의는
아니라고 생각합니다.

처음 글을 읽었을 때 제 느낌을 적어보겠습니다.

개인적으로 어떤 목적으로 이루어지든, 토론이라는 것은 상대방의 주장
하는 바를 온전히 이해한 이후에 자신의 생각을 정리해 보여야 하는
것이라 생각합니다. 경우에 따라 자신의 생각과 너무도 달라 이해가
어려운 경우도 있을 수 있으나 그런 경우 질문과 답변이라는 과정을 통해
상대방이 주장하는 바를 보다 잘 이해할 수 있습니다.

제가 어떤 내용이 사실이 아니라고 강조하고 또 그 근거를 보인 이후,
님께서 제가 올린 내용이 잘못되었다고 판단하신다면 제 근거의 잘못된
부분을 지적하시어 올바른 내용이 될 수 있도록 하는 것이 올바른 방향
이라 생각합니다. (저 역시 제가 드리는 답변이 항상 올바른 내용이라
생각하진 않습니다. 늘 올바른 답변을 드리기 위해 최선을 다하지만, 최근
내부연결/외부연결 명칭에 대한 글에서도 볼 수 있듯이 저 역시 실수를
하고 잘못을 범하고 있습니다.)

하지만, 그와 같은 과정 없이 단지 추측만으로 전혀 상반되는 내용의
주장을 올리셨고, 위에서 말씀드렸듯이 저로서는 제가 드린 답변의 내용이
완전히 무시되고 있다는 느낌을 받지 않을 수 없었습니다. 더구나 독립된
답변으로 올라온 글도 아니고 제 답변 아래에 달리는 댓글에서 그와 같은
느낌을 받았으니 감정적인 부분에서 더 자극받았음을 솔직히 인정합니다.

만약 님께서 제 글을 적절한 부분을 인용하시는 등의 방식으로 제 글의
오류를 찾아내려 하셨다면 그와 같은 형식의 답글은 저 역시 달지 않았을
것입니다. 혹은 제가 답변드린 부분 중에 부족하게 전달한 부분이 있어
질문을 주셨다면 친절히 설명을 드리려 노력했을 것입니다.

믿으실지 모르겠지만, 님 감정 상하시라고 드린 답변이 아닙니다. 제
감정 상태를 표현하기 위한 답변이었습니다. 본의 아니게 상처를 드렸다면
사과의 말씀 드립니다. 하지만, 아직 미숙한 탓에 동일한 상황이 닥쳤을
때 또 다시 같은 행동을 보이지 않으리란 약속은 드리기 어렵습니다. ^^

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

에고.. 제 생각을 한번 더 남겨보죠. 이러다 KLDP 6대 트롤에 합류 하는 게 아닌가 우려됩니다만...

>제가 "...는 사실이 아니다" 라는 주장과 함께 이를 설명하기 위한 근거를
>남겼음에도 불구하고 "...가 사실인 것 같다" 라는 추측성 글을
>남기셨으니,

전웅님께서 "A는 사실이 아니다"라고 주장하셨고, 제가 "B는 사실인 것 같다" 라고 주장했다고 합시다. 여기서 A와 B가 동일하다고 생각하십니까?

전웅님께서 주장하신 "A는 사실이 아니다"라는 주장은

돼지님의 방법 ==
1>>보여주신 방법은 복잡한 선언을 풀어쓴 후에 가장 최종 유도된 type 부터 벗겨내는 과정에 불과하다.
2>>배열이 포인터로 decay 한 후 포인터 연산이 적용될 경우의 결과를 보여주지는 못합니다.
3>>포인터 이해를 위한 방법이라기 보다는
4>>복잡한 선언을 풀어내기 위한 (다소 부족한) 방법에 불과하다.
5>>저는 선언에서 type 유도의 순서를 결정할 때 연산자 우선순위를 그대로 적용할 수 있다는 사실을 설명할 때에만 사용할 뿐 그 이외에는 영어식 표현으로 풀어쓰는 방식을 선호합니다.

입니다. 그렇다면 사실이 아닌 A는 "돼지님 방법은 포인터 이해를 위한 방법이다" 라고 볼 수 있습니다. 1, 2, 4 는 돼지님의 방법에 대한 전웅님의 규정이고, 5는 전웅님께서 돼지님 방법을 사용하는 경우와 자신이 선호하는 방식에 대한 표현이므로 A가 될 수는 없습니다.

제가 주장한 B는 명백히 A가 아닙니다. "B가 사실인 것 같다" 에서의 B는 "돼지님의 방법은 변수가 사용 될 때의 타입을 잘 맞추는 것 같다" 입니다. not A 와 B 가 양립 불가능한 것도 아니고, not A를 근거로 B 를 반박할 수도 없습니다. 돼지님 방법이 "포인터를 이해하는 방법이거나 아니거나"는 제 댓글과는 상관이 없습니다. 여기서 분명히 하셔야 될 것이 어디까지나 '변수가 사용 될 때의 타입' 입니다. 님께서 쓰시는 용어에 의하면 '배열이 포인터로 decay' 된 이후의 타입이겠군요. 만약 님의 주장이 제 주장에 대한 반박이 되려면 "돼지님의 방법대로 하니까 배열이 포인터로 decay 된 이후의 타입이 엄밀하게 해석한 타입과 불일치 하더라"고 하셔야 합니다. 제가 님 댓글 두 개를 모두 읽었을 때는 그런 주장을 하시는 것 같지는 않으시더군요.

>느낌만으로 추측성 답글을 남기기에는 부적절하다고
>생각하지는 않으시는지 궁금합니다. (다양한 결론이 가능한 토론에
>사용되는 것에는 아직도 반대하지만) 점수제가 사용되고 있어 기술적으로
>잘못된 답변이 적절히 가려질 수 있는 점은 다행이지만, 잘못된 내용을
>정확한 논리적 바탕도 없는 추측만으로 작성해 올리는 것이 무책임할 수
>있다는 생각은 안 해보셨는지요?

앞에서도 제가 말씀드렸지만, 제가 주장하고 있는 명제 자체가 "돼지님의 방법은 변수가 사용 될 때의 타입을 잘 맞추는 것 같다" 입니다. 만약 제가 주장하는 바가 "~이다", "항상~이다" 라면, 님의 주장이 맞겠지만, 그것이 아닙니다. 제가 말하고 있는 것은 기술적으로 잘못 될 수가 없습니다. 왜냐하면 주장하고 있는 바가 기술적이지 않기 때문이죠. 제가 주장하는 것은 "변수 사용 시 그 타입을 예측"하는 휴리스틱 혹은 mnemonic 에 대해서 이야기 하고 있습니다. 어떤 변수 표현을 그 휴리스틱에 맞춰서 해석해도 타입이 맞아 떨어지는 것 같다는 것이죠. 그리고 그 휴리스틱 자체가 비논리적이긴 하지만, 제가 어떤 주장을 하는 것 자체는 논리에 따라서 하려고 했습니다.

>제 댓글에 대해 반박을 하고 안 하고의 문제가 아닙니다 - 제 댓글에 반박
>을 했기 때문에 제가 직설적인 표현을 섞어 답변을 달았다고 판단하셨다면
>오해이십니다. 문제는 어떤 내용이 어떤 형식으로 올라왔냐는 것입니다.

이 말씀을 "느낌만으로 추측성 답글을 남기거나" , "잘못된 내용을 정확한 논리적 바탕도 없는 추측만으로 작성하는" 방식으로 공개게시판에 글을 올리면, 직설적인 말을 들어도 어쩔 수 없다라는 뜻으로 받아들여도 되는 것인지요? 과연 이것이 일반적인 공개게시판의 상식에 얼마나 부합하는 지 저는 잘 모르겠습니다. 제가 비상식적인 것일까요? 적어도 저는 제가 남에게 "직설적인" 언사를 하지 않았다면, 제가 "직절적인" 언사를 감수해야 된다고 생각 지는 않습니다만... "스스로의 추측에 무책임"하다고 해서 직설적인 언사를 감수해야 하는 것인 지도 의문스럽고요.

>옳고 그름이 분명한 이야기를 나누는 문맥에서 추측을 바탕으로 한 주장을
>통해 잘못된 내용을 전달하는 것 역시 공개 게시판에 대한 예의는
>아니라고 생각합니다.

앞에서도 언급했듯이 옳고 그름에 대한 문맥이 아닙니다. 처음부터 "당신이 틀리고 내가 맞다"라고 주장한 것이 아니라고 했습니다. 그리고 설령 그런 맥락에서 제가 예의를 못지켰다고 하더라도 그것이 직접적인 언사를 제가 감수해야 될 이유가 될까요?

>하지만, 그와 같은 과정 없이 단지 추측만으로 전혀 상반되는 내용의
>주장을 올리셨고, 위에서 말씀드렸듯이 저로서는 제가 드린 답변의 내용이
>완전히 무시되고 있다는 느낌을 받지 않을 수 없었습니다. 더구나 독립된
>답변으로 올라온 글도 아니고 제 답변 아래에 달리는 댓글에서 그와 같은
>느낌을 받았으니 감정적인 부분에서 더 자극받았음을 솔직히 인정합니다

상반되는 주장이 아닙니다. 님의 주장에 상반되는 주장을 하려면, "돼지님의 방법이 포인터를 이해하는 올바른 방법이다"라고 해야 하는데, 전혀 그런 의도가 아니었습니다. 그리고 전웅님을 무시할 의도가 없었고 답글로 단 이유는 님의 글을 읽다가 생각이 나서 쓴 글이기 때문입니다. 그렇다면 전웅님께서 감정적인 표현을 섞어 글을 쓰신 것은 "완전히 무시되고 있다는 느낌을 받지 않을 수 없어서" 였군요. 과연 이게 제가 님께서 감정적으로 쓴 댓글에 대해 아무 감정없이 "내가 잘못했는 갑다" 하고 감수해야 되는 것인지 전웅님께 묻고 싶습니다.

>만약 님께서 제 글을 적절한 부분을 인용하시는 등의 방식으로 제 글의
>오류를 찾아내려 하셨다면 그와 같은 형식의 답글은 저 역시 달지 않았을
>것입니다. 혹은 제가 답변드린 부분 중에 부족하게 전달한 부분이 있어
>질문을 주셨다면 친절히 설명을 드리려 노력했을 것입니다.

도대체 이해가 안갑니다. 스스로 제 글이 님 글을 반박하지 않았다는 점을 인정하시면서도, 제 글이 님 글을 무시하는 것으로 느껴졌다니 참 의문스럽습니다. 님 글의 오류에 대한 지적이 아닌데, 어떻게 님께서 제시한 방식의 글을 쓸 수가 있을까요?

>믿으실지 모르겠지만, 님 감정 상하시라고 드린 답변이 아닙니다. 제
>감정 상태를 표현하기 위한 답변이었습니다. 본의 아니게 상처를 드렸다면
>사과의 말씀 드립니다. 하지만, 아직 미숙한 탓에 동일한 상황이 닥쳤을
>때 또 다시 같은 행동을 보이지 않으리란 약속은 드리기 어렵습니다. ^^

스스로 감정적인 글이었다는 것을 인정하시면서 감정 상하게 할 의도는 아니었다고 하시니, 제가 머라고 말씀을 드려야 할 지 모르겠습니다. 제 글을 일일이 인용하시면서 감정적인 표현을 섞으셨으면서 말이죠. 저도 감정 사움을 떠나서 제 생각이 좀 더 명확하게 된 것에 대해서는 감사를 드려야 겠군요. 특히 decay 나 유도 같은 표현에 있어서 말이죠.

그리고 마지막으로 님께서 제시한 예에 대해서,

>> 논리가 이러한 유도의 순서를 무시할 수 있는 것이라면
>> int (*func)(void);
>> 에서 func() 의 결과는 int * 가 되어야 하는지요? 유사하게

아닙니다. func() 는 돼지님께서 사용하신 방법으로 추측이 불가능 합니다. 왜냐하면 func() 라는 모양이 선언에 없기 때문입니다. (*func)() 가 int 인것은 맞겠지요.

>> int (*parr)[10];
>> 에서 parr[n] 의 결과는 int * 가 되어야 하는지요?

parr[n] 모양 또한 선언 내에 없습니다.

모양 내에 있는 *parr 에 대해서 보면,
1) (*parr) 가 int[10] -> int 배열 -> 사용시에 포인터 -> 따라서 '사용'시 pointer to int 일 것이다.

2) parr 은 읽어보면 pointer to array of int 이므로 *parr는 array of int 입니다. 따라서 사용 시에는 pointer to int 죠. 여기서 사용이라는 것은 님께서 말씀하신 '배열이 포인터로 decay 된 후' 라는 맥락입니다.

제가 말씀 드리는 것이 "1)로 하나 2)로 하나 결과가 일치한는 것 같다" 라는 주장일 뿐입니다.

parr[n] 은 parr 이가 pointer to array of int 이므로, *(parr+n) 은 array of int 타입이겠네요. 결국 사용시에는 pointer to int 가 되어야 할 것 같은데 아닌가요?

그리고,
sizeof(expression) 이, expression 이 나타내는 타입을 결정해 주지는 못합니다. 예를 들어

int *parr1[10];
int *parr2[10];

에서 sizeof(parr1) 과 parr2 에서 parr1과 parr2 타입은 서로 다릅니다. parr1 은 포인터로 변환이 안되지만, parr2는 포인터로 변하기 때문입니다. 제가 parr1 의 타입도 포인터라고 주장한다고 생각하시는 것 같은데, sizeof(parr1) 은 선언의 모양에 없습니다. 따라서 돼지님 방식으로는 형 결정이 불가능 하죠. sizeof(parr1+0) 가 sizeof(parr1) 과는 다른 값을 출력하는 것만 보아도, sizeof 값이 특정 표현의 타입을 결정해 주지는 못합니다. sizeof 안에 들어가 있을 때 parr1 과 parr1+0 의 타입은 다르지만, 그냥 parr1, parr1+0 이라는 표현의 타입은 같습니다. 제가 볼 때는 전웅님께서도 동의하시리라 생각합니다.

그리고 저도 별로 이 방법이 좋다고 생각하지 않습니다.

제가 변수를 읽을 때 쓰는 방법은

int (*parr)[10]의 경우

(*parr)[6] 은 int
(*parr) 은 array of int
parr 은 pointer to array of int
*parr 은 pointer dereferecing 따라서 array of int

int *parr[10]의 경우

*parr[6] 은 int
parr[6] 은 pointer to int
parr 은 array of pointer to int
*parr 은 parr[0] 이므로, pointer to int

이런식이지, 결코 연산의 순서를 무시하지 않습니다. 이름 중심으로 읽는 것과 크게 다를 바도 없습니다.

제가 일전에 쓴 댓 글의 내용이나 표현이 정확하지 못하고, 무슨 말 하는 글인지 잘 모르겠다는 점에 대해서는 인정하겠습니다만, 전웅님께서 제 글에 대해서 "직설적으로" 표현하신 것이 정당화 되지는 않는 듯 합니다. 님께서 쓰신 글을 보아, 옳고 그름을 가리는 맥락에서 논리적인 글에 대해 느낌과 추측으로 정 반대의 주장을 하면, "직설적인" 표현을 사용해서 댓글을 달아도 된다고 생각하시는 것 같습니다. 그러나 제가 아는 어떤 상식으로도 이해가 되질 않는군요. 위에서 설명했듯이 정반대의 주장을 하지도 않았고, 하였다고 하더라도 과연 "직설적으로" 글을 쓰셔도 되는 것인지에 대해서 묻고 싶습니다. 비유적으로 표현하면 어떤 사람 논문을 읽고 나서, 내 생각에는 이런 이유 때문에 틀린 것 같아~ 라고 말하면, 그 사람이 "직설적으로" 저한테 표현해도 된다는 것 같습니다. 님의 댓글을 보고 나니 더욱 당황스럽군요 ;;

전웅의 이미지

[...]
> >제가 "...는 사실이 아니다" 라는 주장과 함께 이를 설명하기 위한 근거를
> >남겼음에도 불구하고 "...가 사실인 것 같다" 라는 추측성 글을
> >남기셨으니,
>
> 전웅님께서 "A는 사실이 아니다"라고 주장하셨고, 제가 "B는 사실인 것 같다" 라고
> 주장했다고 합시다. 여기서 A와 B가 동일하다고 생각하십니까?
>
> 전웅님께서 주장하신 "A는 사실이 아니다"라는 주장은
>
> 돼지님의 방법 ==
> 1>>보여주신 방법은 복잡한 선언을 풀어쓴 후에 가장 최종 유도된 type 부터 벗겨내는 과정에 불과하다.
> 2>>배열이 포인터로 decay 한 후 포인터 연산이 적용될 경우의 결과를 보여주지는 못합니다.
> 3>>포인터 이해를 위한 방법이라기 보다는
> 4>>복잡한 선언을 풀어내기 위한 (다소 부족한) 방법에 불과하다.
> 5>>저는 선언에서 type 유도의 순서를 결정할 때 연산자 우선순위를 그대로 적용할 수 있다는 사실을 설명할 때에만 사용할 뿐 그 이외에는 영어식 표현으로 풀어쓰는 방식을 선호합니다.
>
> 입니다. 그렇다면 사실이 아닌 A는 "돼지님 방법은 포인터 이해를 위한 방법이다"
> 라고 볼 수 있습니다. 1, 2, 4 는 돼지님의 방법에 대한 전웅님의 규정이고, 5는
> 전웅님께서 돼지님 방법을 사용하는 경우와 자신이 선호하는 방식에 대한
> 표현이므로 A가 될 수는 없습니다.
>

이거 보십시오. 님은 제 글을 올바르게 이해하지 못하는 상태에서 계속해서
답을 하고 계십니다. 이러니 오해만 깊어지는 것입니다. 제 글을 다시
인용해 보겠습니다. 제가 사실이 아니라고 주장한 것은 이 논의에서 무려
2번이나 언급되고 있습니다.

제가 씀:
] 같은 논리라면,
]
] int *parr[10];
]
] 에서 *parr 이라고 쓰면 int [10] 이 남으니 배열이 되어야 겠군요!
] (물론, 아니라는 얘깁니다!! --;)

즉, "*parr 을 빼고 int [10] 이 남았기에 *parr 이 배열이 되는 것은
아니다" 라는 것이 제가 주장했던 바이고, 이에 대해 님은

] int *parr[10];
] *parr 는 int[10], *parr 는 int 배열, ...

라고 답한 바 있습니다.

이제 제가 사실이 아니라고 주장하는 바와 님이 사실이라고 주장하는 바가
같다는 것이 분명해졌는지요?

A = "*parr 이라고 쓰면 int [10] 이 남으니 배열이 된다"
B = "*parr 은 int [10] 따라서 *parr 는 int 배열

이제 A == B 임이 보이시리라 믿습니다.

> 제가 주장한 B는 명백히 A가 아닙니다. "B가 사실인 것 같다" 에서의 B는 "돼지님의
> 방법은 변수가 사용 될 때의 타입을 잘 맞추는 것 같다" 입니다. not A 와 B 가
> 양립 불가능한 것도 아니고, not A를 근거로 B 를 반박할 수도 없습니다. 돼지님
> 방법이 "포인터를 이해하는 방법이거나 아니거나"는 제 댓글과는 상관이 없습니다.

따라서 이 부분은 무의미한 주장이 됩니다. 편의를 위해 위에서 보인
오해로 인해 님이 말씀하신 부분은 생략하며 답변을 달도록 하겠습니다.

> 여기서 분명히 하셔야 될 것이 어디까지나 '변수가 사용 될 때의 타입' 입니다.
> 님께서 쓰시는 용어에 의하면 '배열이 포인터로 decay' 된 이후의 타입이겠군요.

"변수가 사용될 때의 타입" 이라는 개념을 마음대로 정의해 사용하고
계시는군요. sizeof(*parr) 에서도 parr 이 사용되고 있습니다. 님의 논리
를 그대로 적용하자면

int a[10];
 
sizeof(a);
&a;
a[0] = 0;

에서 위에서 두 a 의 type 은 array, 마지막 a 의 type 은 pointer 가
되겠군요. C 언어에서 변수의 type 이 문맥에 따라 달라질 수 있다고 주장
하시는 것인지 궁금합니다 - C99 의 VLA 를 제외하면 C 언어에서 모든 변수
의 type 은 정적으로 결정됩니다.

아니면, a 의 type 은 array 인데, a 를 "사용할 때의" type 은 pointer 가
되는 것인지요? 만약, 그렇다면 님은 다른 통용될 수 없는 님만의 개념과
방법론으로 C 언어를 정의, 해석하고 계시는 것에 해당합니다.

* 관련 내용이 아래 다시 언급됩니다.

> 만약 님의 주장이 제 주장에 대한 반박이 되려면 "돼지님의 방법대로 하니까 배열이
> 포인터로 decay 된 이후의 타입이 엄밀하게 해석한 타입과 불일치 하더라"고 하셔야
> 합니다. 제가 님 댓글 두 개를 모두 읽었을 때는 그런 주장을 하시는 것 같지는
> 않으시더군요.

제가 씀:
] 님이 말씀하시는 (*parr 을
] 통해 포인터로 접근하게 되는) "배열"이 int [10] 이 말하는 그 "배열"이
] 아닙니다!

전자의 "배열"이 님이 말씀하시는 포인터를 통해 접근하게 되는 배열 (이
배열의 크기는 해당 포인터가 가리키는 배열에 따라 달라집니다), 후자의
배열이 int [10] 이 표현하는 배열입니다. 제가 너무 글을 간단히 적어
제대로 전달이 되지 않았나 봅니다. 어떤 분은 글이 너무 지리하다 하시고,
그래서 간단히 적으니 다른 분에게는 뜻이 전달되지 않는군요. :-(

> >느낌만으로 추측성 답글을 남기기에는 부적절하다고
> >생각하지는 않으시는지 궁금합니다. (다양한 결론이 가능한 토론에
> >사용되는 것에는 아직도 반대하지만) 점수제가 사용되고 있어 기술적으로
> >잘못된 답변이 적절히 가려질 수 있는 점은 다행이지만, 잘못된 내용을
> >정확한 논리적 바탕도 없는 추측만으로 작성해 올리는 것이 무책임할 수
> >있다는 생각은 안 해보셨는지요?
>
> 앞에서도 제가 말씀드렸지만, 제가 주장하고 있는 명제 자체가 "돼지님의 방법은
> 변수가 사용 될 때의 타입을 잘 맞추는 것 같다" 입니다. 만약 제가 주장하는 바가
> "~이다", "항상~이다" 라면, 님의 주장이 맞겠지만, 그것이 아닙니다. 제가 말하고
> 있는 것은 기술적으로 잘못 될 수가 없습니다. 왜냐하면 주장하고 있는 바가 기술적
> 이지 않기 때문이죠. 제가 주장하는 것은 "변수 사용 시 그 타입을 예측"하는
> 휴리스틱 혹은 mnemonic 에 대해서 이야기 하고 있습니다. 어떤 변수 표현을 그
> 휴리스틱에 맞춰서 해석해도 타입이 맞아 떨어지는 것 같다는 것이죠. 그리고 그
> 휴리스틱 자체가 비논리적이긴 하지만, 제가 어떤 주장을 하는 것 자체는 논리에
> 따라서 하려고 했습니다.
>

제가 드린 말씀은 그 휴리스틱 (솔직히 휴리스틱이라는 단어를 붙이기에는
너무 비논리적입니다만) 이 잘못되었다는 것입니다. 즉, "돼지님의 방법은
변수가 사용될 때의 type 을 잘 맞추는 것 같다" 도 거짓이라는 이야기
입니다.

> >제 댓글에 대해 반박을 하고 안 하고의 문제가 아닙니다 - 제 댓글에 반박
> >을 했기 때문에 제가 직설적인 표현을 섞어 답변을 달았다고 판단하셨다면
> >오해이십니다. 문제는 어떤 내용이 어떤 형식으로 올라왔냐는 것입니다.
>
> 이 말씀을 "느낌만으로 추측성 답글을 남기거나" , "잘못된 내용을 정확한 논리적
> 바탕도 없는 추측만으로 작성하는" 방식으로 공개게시판에 글을 올리면, 직설적인
> 말을 들어도 어쩔 수 없다라는 뜻으로 받아들여도 되는 것인지요? 과연 이것이
> 일반적인 공개게시판의 상식에 얼마나 부합하는 지 저는 잘 모르겠습니다. 제가
> 비상식적인 것일까요? 적어도 저는 제가 남에게 "직설적인" 언사를 하지 않았다면,
> 제가 "직절적인" 언사를 감수해야 된다고 생각 지는 않습니다만... "스스로의
> 추측에 무책임"하다고 해서 직설적인 언사를 감수해야 하는 것인 지도 의문스럽고요.

저는 충분히 제가 처음 님의 글을 보았을 때 느꼈던 감정적 상태를 설명한
바 있습니다. 제 감정적 상태를 님께서 굳이 이해하실 필요는 없습니다.
말씀드렸듯이, 저는 님의 감정을 상하게 하기 위한 목적이 아니라 제
감정을 표현하기 위한 글을 썼고, 이 때문에 님의 감정이 상하셨다면 이는
제 의도가 아니므로 다시 한번 사과드립니다. 제가 해드릴 수 있는 것은
여기까지입니다. 뭐 제가 있는 곳으로 찾아라도 오신다면 술이라도 한잔
대접하겠지만, 그럴 수 없으니 글로써 사과드리는 것이 제가 할 수 있는
전부입니다.

마찬가지로 불필요한 감정 싸움을 피하기 위해 님께서 말씀하신 감정적인
표현에 대한 부분도 가급적 생략하도록 하겠습니다.

[...]

> 그리고 전웅님을 무시할 의도가 없었고 답글로 단 이유는 님의 글을 읽다가 생각이
> 나서 쓴 글이기 때문입니다. 그렇다면 전웅님께서 감정적인 표현을 섞어 글을 쓰신
> 것은 "완전히 무시되고 있다는 느낌을 받지 않을 수 없어서" 였군요. 과연 이게
> 제가 님께서 감정적으로 쓴 댓글에 대해 아무 감정없이 "내가 잘못했는 갑다" 하고
> 감수해야 되는 것인지 전웅님께 묻고 싶습니다.
>

전 님께서 잘못하지 않으셨다고 생각하진 않습니다. 님께서 잘못된 사실을
추측만을 바탕으로 주장하셨다는 사실은 변함이 없습니다. 또한, 그와 같은
주장이 제가 말씀드린 사실에 정확히 반한다는 사실도 (이미 근거를
보였듯이) 분명합니다. 즉, 님이 잘못하셨다는 사실과 님이 그와 같은
감정적 대우를 받아야 한다는 것은 분리될 수 있는 문제입니다. 님은 잘못
하셨고 저 때문에 감정적으로 상처를 받으실 필요는 없었습니다 - 따라서
제가 감정적인 부분에 대해서는 사과를 드렸던 것입니다.

> >만약 님께서 제 글을 적절한 부분을 인용하시는 등의 방식으로 제 글의
> >오류를 찾아내려 하셨다면 그와 같은 형식의 답글은 저 역시 달지 않았을
> >것입니다. 혹은 제가 답변드린 부분 중에 부족하게 전달한 부분이 있어
> >질문을 주셨다면 친절히 설명을 드리려 노력했을 것입니다.
>
> 도대체 이해가 안갑니다. 스스로 제 글이 님 글을 반박하지 않았다는 점을 인정하시면서도,
> 제 글이 님 글을 무시하는 것으로 느껴졌다니 참 의문스럽습니다. 님 글의 오류에
> 대한 지적이 아닌데, 어떻게 님께서 제시한 방식의 글을 쓸 수가 있을까요?
>

제 글의 의도가 제대로 전달이 되지 않은 듯 합니다. 제 글의 오류에 대한
지적이 근거에 대해 논리적으로 이루어졌더라면 차라리 나았을 것이었다는
뜻입니다. 제가 전달하고자 한 사실이 비논리적인 근거를 바탕으로한
일방적인 반대 주장에 의해 무시되었다는 뜻이었습니다.

[...]

> 그리고 마지막으로 님께서 제시한 예에 대해서,
>
> >> 논리가 이러한 유도의 순서를 무시할 수 있는 것이라면
> >> int (*func)(void);
> >> 에서 func() 의 결과는 int * 가 되어야 하는지요? 유사하게
>
> 아닙니다. func() 는 돼지님께서 사용하신 방법으로 추측이 불가능 합니다. 왜냐하면 func() 라는 모양이 선언에 없기 때문입니다.
> (*func)() 가 int 인것은 맞겠지요.
>

int *func(void); 는 int *(func(void)); 와 완전히 동일합니다. 그렇다면
이번에는 *func 라는 모양이 선언에 없는 셈입니다. 유사한 이야기가 *parr
에 대해서도 계속 전개됩니다.

>> int (*parr)[10];
>> 에서 parr[n] 의 결과는 int * 가 되어야 하는지요?
>
> parr[n] 모양 또한 선언 내에 없습니다.
>
> 모양 내에 있는 *parr 에 대해서 보면,
> 1) (*parr) 가 int[10] -> int 배열 -> 사용시에 포인터 -> 따라서 '사용'시 pointer to int 일 것이다.
>
> 2) parr 은 읽어보면 pointer to array of int 이므로 *parr는 array of int 입니다. 따라서 사용 시에는 pointer to int 죠.
>

넵 여기까지는 맞는 추론입니다. 하지만, 기억하시는지 모르겠지만 님이
주장하셨던 내용은 int (*parr)[10] 이 아닌 int *parr[10] 에 대한
것이었습니다.

int *parr[10]; 은 int *(parr[10]); 와 완전히 동일합니다. 그렇다면
이번에는 *parr 이라는 모양이 선언에 없는 셈입니다. 그럼에도 님은
중복된 괄호가 선언에서 생략되었다는 사실만으로 int *parr[10]; 이라는
선언에서 *parr 의 의미가 int [10] 이라고 주장하셨던 것입니다. 여기에
님께서 주장하셨던 바의 논리적 오류가 있습니다.

>
> parr[n] 은 parr 이가 pointer to array of int 이므로, *(parr+n) 은 array of int 타입
> 이겠네요. 결국 사용시에는 pointer to int 가 되어야 할 것 같은데 아닌가요?
>

님께서 이와 유사한 내용을 주장하셨던 선언은 제가 위에서 적은 int
(*parr)[10]; 이 아니라 전혀 다른 선언인 int *(parr[10]); 이었습니다.
int (*parr)[10] 에 대해서는 맞는 내용이며, int *(parr[10]) 에 대해서는
잘못된 내용입니다.

>
> 그리고,
> sizeof(expression) 이, expression 이 나타내는 타입을 결정해 주지는 못합니다. 예를 들어
>
> int *parr1[10];
> int *parr2[10];
>
> 에서 sizeof(parr1) 과 parr2 에서 parr1과 parr2 타입은 서로 다릅니다.

parr1 과 parr2 의 type 은 동일합니다. 배열과 포인터는 다른 type 입니다.
배열이 특정 문맥에서 포인터로 변환되는 것 뿐입니다. 님의 주장은 마치
사과를 공기 중에 오래 두면 갈변하기 때문에, "사과는 진공 속과 공기
속에서 원래부터 다른 색을 갖는다" 라는 주장과 별반 다르지 않아
보입니다.

> parr1 은
> 포인터로 변환이 안되지만, parr2는 포인터로 변하기 때문입니다. 제가 parr1 의
> 타입도 포인터라고 주장한다고 생각하시는 것 같은데, sizeof(parr1) 은 선언의
> 모양에 없습니다. 따라서 돼지님 방식으로는 형 결정이 불가능 하죠.
> sizeof(parr1+0) 가 sizeof(parr1) 과는 다른 값을 출력하는 것만 보아도, sizeof
> 값이 특정 표현의 타입을 결정해 주지는 못합니다.

또 다시 부족한 근거를 바탕으로 잘못된 내용을 주장하고 계십니다. sizeof
연산자의 피연산자로 수식(expression)이 오면, 그 수식의 type 을 바탕
으로 결과가 결정됩니다. 즉, sizeof 연산자는 특정 표현의 type 을 근거로
동작합니다. 지금 하고 계신 주장은 언어 "정의"까지 부정하고 계신
것입니다. 원하신다면 근거라도 인용해 드릴 수 있습니다.

> sizeof 안에 들어가 있을 때
> parr1 과 parr1+0 의 타입은 다르지만, 그냥 parr1, parr1+0 이라는 표현의 타입은
> 같습니다. 제가 볼 때는 전웅님께서도 동의하시리라 생각합니다.
>

좋습니다. 무엇을 말씀하고자 하시는지 의도를 제가 대충 파악했으므로
그럼 이렇게 말씀드려 보겠습니다.

#1

int *parr[10];

에서 *parr 이 님이 말씀하시는 선언에 포함되어 있는 "모양"입니까?
(int *parr[10]; 은 사실 int *(parr[10]); 임에 유의하시기 바랍니다)

#2

님의 주장대로 *parr 의 type 이 남아있는 int [10] 이고 *parr 이라는
"사용에 의해" pointer to int 가 되는 것이라면, 그 포인터가 가리키는
배열이 갖는 요소 개수에 대해 이야기를 해보겠습니다. 만약, 진정 *parr
의 type 이 int [10] 이라면 *parr 이라는 사용에 의해 나타난 포인터는
모두 10개의 int 를 가리킬 수 있어야 합니다. 그렇다면 *parr + 10 은
선언에 의해 항상 유효한 수식입니까?

이 두 가지 질문에 답을 하는 과정만으로 충분히 그 차이가 설명되리라
믿어 의심치 않습니다.

> 그리고 저도 별로 이 방법이 좋다고 생각하지 않습니다.
>
> 제가 변수를 읽을 때 쓰는 방법은
>
> int (*parr)[10]의 경우
>
> (*parr)[6] 은 int
> (*parr) 은 array of int
> parr 은 pointer to array of int
> *parr 은 pointer dereferecing 따라서 array of int
>
> int *parr[10]의 경우
>
> *parr[6] 은 int
> parr[6] 은 pointer to int
> parr 은 array of pointer to int
> *parr 은 parr[0] 이므로, pointer to int
>

C 언어에서 명칭에서 먼 선언자부터 벗겨가며 type 을 기술하는 방법
입니다. 이는 올바른 방법입니다. 일반적으로 명칭에 가장 먼저 적용된
declarator 부터 해석하는 것이 영어권에서는 유리하지만, 수식어가 뒤에
붙는 우리 말에서는 이 방법이 유리할 수도 있습니다.

> 이런식이지, 결코 연산의 순서를 무시하지 않습니다. 이름 중심으로 읽는 것과 크게 다를 바도 없습니다.
>

그런 분이 왜 이전에는 그와 같은 잘못된 주장을 하셨는지 모르겠습니다.

> 제가 일전에 쓴 댓 글의 내용이나 표현이 정확하지 못하고, 무슨 말 하는 글인지 잘
> 모르겠다는 점에 대해서는 인정하겠습니다만,

분명히 하자면, precise 하지 못한 것이 아니라 correct 하지 못했던 것
입니다.

> 전웅님께서 제 글에 대해서 "직설적으로" 표현하신 것이 정당화 되지는 않는 듯
> 합니다. 님께서 쓰신 글을 보아, 옳고 그름을 가리는 맥락에서 논리적인 글에 대해
> 느낌과 추측으로 정 반대의 주장을 하면, "직설적인" 표현을 사용해서 댓글을
> 달아도 된다고 생각하시는 것 같습니다.

"생각하시는 것 같습니다" 는 님의 생각일 뿐입니다. 제가 한번이라도
님께서는 그와 같은 대우를 받으셔도 괜찮다고 말씀드린 부분이 있는지
궁금합니다. 자신에게 유리한 상황으로 감정적 문제를 끌고가지 않으셨으면
좋겠습니다.

> 그러나 제가 아는 어떤 상식으로도 이해가 되질 않는군요. 위에서 설명했듯이
> 정반대의 주장을 하지도 않았고,

하셨습니다.

> 하였다고 하더라도 과연 "직설적으로" 글을 쓰셔도 되는 것인지에 대해서 묻고
> 싶습니다.

마지막으로 사과의 말씀 다시 드립니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

제 글입니다
>선언과 사용을 대조해 보면,
>int a[10];
>a는 int[10], a 는 int 배열, 그런데 씨에서 배열을 지칭할 때 포인터를 사용하므로 pointer to int
>int *parr[10];
>*parr 는 int[10], *parr 는 int 배열, 똑같이 pointer to int
>단 *parr[3] 은 int, parr[3] 은 pointer to int
>중간 과정은 이상해도 결과는 대충 맞는듯 합니다만 :)

전 분명히 "중간 과정은 이상해도 결과는 대충 맞는 듯 하다." 고 주장했습니다. 이 부분에 대해서 오해가 풀리셨으면 좋겠습니다만, 제가 주장한건 "a가 int 배열이다" 혹은 *parr int 배열이다"라고 주장한 것이 아닙니다. 그래서 "중간과정" 이 이상하다고 했습니다. 저기서 a 는 int 배열 운운한 것은 그냥 하나의 사고 과정이었지요. 안그랬으면 왜 중간과정이 이상하다고 운을 땠겠습니까?

>이제 제가 사실이 아니라고 주장하는 바와 님이 사실이라고 주장하는 바가
>같다는 것이 분명해졌는지요?
>
>A = "*parr 이라고 쓰면 int [10] 이 남으니 배열이 된다"
>B = "*parr 은 int [10] 따라서 *parr 는 int 배열
>이제 A == B 임이 보이시리라 믿습니다

위에서 언급했듯이 B가 제가 주장한 바가 "아닙니다"

제발 이제는 이 부분에 대해서 오해가 없기를 바라며, 글 자체가 모호한 것은 저도 인정합니다.

>"변수가 사용될 때의 타입" 이라는 개념을 마음대로 정의해 사용하고
>계시는군요. sizeof(*parr) 에서도 parr 이 사용되고 있습니다. 님의 논리
>를 그대로 적용하자면
>
>int a[10];
>
>sizeof(a);
>&a;
>a[0] = 0;
>
>에서 위에서 두 a 의 type 은 array, 마지막 a 의 type 은 pointer 가
>되겠군요.

예, 말씀하신 대로입니다. 그리고 sizeof(*parr) 에서 parr 은 포인터 타입이고, *parr 은 그 포인터가 가르키고 잇는 pointer to int 여서 sizeof(pointer to int) 와 같은 값이 반환되는 것이 아닌가요?

>C 언어에서 변수의 type 이 문맥에 따라 달라질 수 있다고 주장
>하시는 것인지 궁금합니다 - C99 의 VLA 를 제외하면 C 언어에서 모든 변수
>의 type 은 정적으로 결정됩니다.

C99 에서 VLA 가 무엇인지는 모르겠지만 정적으로 결정 된다는 말에 동의 합니다. 그런데, 변수의 타입이 정적이라고 해서, 변수를 가지고 만든 표현이 항상 같은 타입인 것은 아닙니다. 당장에 C에서 int a[10] 이란 선언 하에서, a라는 변수는 "array of int" 지만, a라는 독립적인 표현은 "pointer to int" 입니다. K&R 2nd edition 200 페이지에, 몇 가지 예외 사항을 제외하고, 어떤 표현이 배열일 때 그 표현의 배열은 포인터로 alter 된다고 나와 있습니다. C99 에서 이 부분이 바꼈을 것이라고는 생각지 않습니다. a 라는 변수가 배열이고 , a 라는 표현이 포인터라고 해서 동적 타이핑 언어가 되거나 하지 않습니다. 어차피 다 컴파일 타임에 형 결정이 날테니까요. 문법 규칙에 따라서 말이죠.

>아니면, a 의 type 은 array 인데, a 를 "사용할 때의" type 은 pointer 가
>되는 것인지요? 만약, 그렇다면 님은 다른 통용될 수 없는 님만의 개념과
>방법론으로 C 언어를 정의, 해석하고 계시는 것에 해당합니다.

맞습니다. 변수 a와 표현 a의 타입이 같다고 주장하시는 것이라면 저는 아니라고 생각합니다.

전웅님 씀:
>] 님이 말씀하시는 (*parr 을
>] 통해 포인터로 접근하게 되는) "배열"이 int [10] 이 말하는 그 "배열"이
>] 아닙니다!
>
>전자의 "배열"이 님이 말씀하시는 포인터를 통해 접근하게 되는 배열 (이
>배열의 크기는 해당 포인터가 가리키는 배열에 따라 달라집니다), 후자의
>배열이 int [10] 이 표현하는 배열입니다. 제가 너무 글을 간단히 적어
>제대로 전달이 되지 않았나 봅니다. 어떤 분은 글이 너무 지리하다 하시고,
>그래서 간단히 적으니 다른 분에게는 뜻이 전달되지 않는군요. :-(

앞에서 밝혔듯이 중간과정은 이상하지만 결과는 대충 맞는다고 했습니다. 중간과정이 이상하다고 말씀드리고 시작했는데, 계속 중간과정에 대해서 말씀하시는군요.

>제가 드린 말씀은 그 휴리스틱 (솔직히 휴리스틱이라는 단어를 붙이기에는
>너무 비논리적입니다만) 이 잘못되었다는 것입니다. 즉, "돼지님의 방법은
>변수가 사용될 때의 type 을 잘 맞추는 것 같다" 도 거짓이라는 이야기
>입니다.

그러니까 마지막 결과물이 틀린 경우를 보여 주시면 감사하겠습니다. 제가 그게 항상 참이라고 딱히 주장하는 것도 아니구요. 님께서 주장하신 어느 부분에도 마지막 결과물이 틀린 경우는 없었습니다.

>저는 충분히 제가 처음 님의 글을 보았을 때 느꼈던 감정적 상태를 설명한
>바 있습니다. 제 감정적 상태를 님께서 굳이 이해하실 필요는 없습니다.
>말씀드렸듯이, 저는 님의 감정을 상하게 하기 위한 목적이 아니라 제
>감정을 표현하기 위한 글을 썼고, 이 때문에 님의 감정이 상하셨다면 이는
>제 의도가 아니므로 다시 한번 사과드립니다. 제가 해드릴 수 있는 것은
>여기까지입니다. 뭐 제가 있는 곳으로 찾아라도 오신다면 술이라도 한잔
>대접하겠지만, 그럴 수 없으니 글로써 사과드리는 것이 제가 할 수 있는
>전부입니다.
>
>마찬가지로 불필요한 감정 싸움을 피하기 위해 님께서 말씀하신 감정적인
>표현에 대한 부분도 가급적 생략하도록 하겠습니다.

님의 감정 상태를 제가 알 필요는 없습니다. 제가 감정이 상했다면 "제가 감정적인 언사를 사용하지 않았는데" 님께서 사용했다는 부분일 것입니다.
만약 님께서 제 글에 대해서 중립적인 언사로 말씀하셨으면 아무 상관도 없었을 것입니다. "요즘 참 이상합니다. 제가 어떤 부분이 사실이 아니라고 느낌표까지 찍어가며 글을 남겨도", "제 표현이 과격하다고 생각하지 마시기 바랍니다." 이렇게 말씀 하시면서 읽는 사람에게 불쾌감을 안 줄 수 있다고 생각하시는지요? (과격하다고 생각하지 마시기 바랍니다를 가만히 분석해 보면 "내 말이 과격했다는 것을 나도 알지만, 그 정도 과격한 표현을 좀 들어도 된다 내지는 들어야 한다"는 뜻으로 보입니다만 ;; 다르게 해석해보려고 해도 어렵군요. 아니면 표현이 과격한 것은 나도 알지만 그냥 안 과격한 표현이라고 생각해주기를 바라는 것이었는지 ;;)

>int *func(void); 는 int *(func(void)); 와 완전히 동일합니다. 그렇다면
>이번에는 *func 라는 모양이 선언에 없는 셈입니다. 유사한 이야기가 *parr
>에 대해서도 계속 전개됩니다.

그냥 모양만 찾아보죠. *func 는 어째든 선언에서 보이지 않습니까? :)

>넵 여기까지는 맞는 추론입니다. 하지만, 기억하시는지 모르겠지만 님이
>주장하셨던 내용은 int (*parr)[10] 이 아닌 int *parr[10] 에 대한
>것이었습니다.
>int *parr[10]; 은 int *(parr[10]); 와 완전히 동일합니다. 그렇다면
>이번에는 *parr 이라는 모양이 선언에 없는 셈입니다. 그럼에도 님은
>중복된 괄호가 선언에서 생략되었다는 사실만으로 int *parr[10]; 이라는
>선언에서 *parr 의 의미가 int [10] 이라고 주장하셨던 것입니다. 여기에
>님께서 주장하셨던 바의 논리적 오류가 있습니다.

저는 "단순히" 사용된 모양만 본 것 입니다. 진짜 단순하게요. *parr 이라는 모양은 int *parr[10]; 과 int (*parr)[10] 에 둘 다 있네요. 그럼 그걸 제외하고 int[10] -> int 배열이네 -> 배열은 사용시에 포인터~ -> *parr 은 결론은 *parr 이 사용될 때는 pointer to int 타입인 거 같다. 입니다. 혹시나 해서 *parr이 int 타입이다라고 주장하는 것은 아니라고 다시 한번 밝힙니다. 앞의 선언과 뒤의 선언에서 *parr 이 가르키는 바는 당연히~ 다릅니다. 모양 보고 타입 결정이지 가르키는 바가 같다고 하지는 않았습니다.

>> parr[n] 은 parr 이가 pointer to array of int 이므로, *(parr+n) 은 array of int 타입
>> 이겠네요. 결국 사용시에는 pointer to int 가 되어야 할 것 같은데 아닌가요?
>>
>님께서 이와 유사한 내용을 주장하셨던 선언은 제가 위에서 적은 int
>(*parr)[10]; 이 아니라 전혀 다른 선언인 int *(parr[10]); 이었습니다.
>int (*parr)[10] 에 대해서는 맞는 내용이며, int *(parr[10]) 에 대해서는
>잘못된 내용입니다.

int *parr[10] 이라는 선언에 대해서 parr[n] 이 사용될 때를 보면, 변수 parr 의 타입은 'array of pointer to int' 이고, 따라서 parr[n] 은 pointer to int 입니다. 여기서도 *(parr+n) 인 것은 매한가지구요.저는 어디 까지나 표현의 타입에 대한 이야기이지 두 선언의 경우에 *parr 이 같은 것을 가르킨다고 하는 것이 아닙니다. 두 경우에 *parr 이 포인터가 아닌 타입으로 사용되는 표현이 있는지 궁금합니다. sizeof(*parr) 에서 *parr 이나, &(*parr) 등등에서 *parr 이 포인터다 배열이다의 문제가 아닌 *parr 이라는 하나의 독립된 표현이 포인터 이외의 것으로 해석될 수 있는 지에 대한 질문입니다.

>> 그리고,
>> sizeof(expression) 이, expression 이 나타내는 타입을 결정해 주지는 못합니다. 예를 들어
>>
>> int *parr1[10];
>> int *parr2[10];
>>
>> 에서 sizeof(parr1) 과 parr2 에서 parr1과 parr2 타입은 서로 다릅니다.
>parr1 과 parr2 의 type 은 동일합니다. 배열과 포인터는 다른 type 입니다.
>배열이 특정 문맥에서 포인터로 변환되는 것 뿐입니다. 님의 주장은 마치
>사과를 공기 중에 오래 두면 갈변하기 때문에, "사과는 진공 속과 공기
>속에서 원래부터 다른 색을 갖는다" 라는 주장과 별반 다르지 않아
>보입니다.
>> parr1 은
>> 포인터로 변환이 안되지만, parr2는 포인터로 변하기 때문입니다. 제가 parr1 의
>> 타입도 포인터라고 주장한다고 생각하시는 것 같은데, sizeof(parr1) 은 선언의
>> 모양에 없습니다. 따라서 돼지님 방식으로는 형 결정이 불가능 하죠.
>> sizeof(parr1+0) 가 sizeof(parr1) 과는 다른 값을 출력하는 것만 보아도, sizeof
>> 값이 특정 표현의 타입을 결정해 주지는 못합니다.
>>
>또 다시 부족한 근거를 바탕으로 잘못된 내용을 주장하고 계십니다. sizeof
>연산자의 피연산자로 수식(expression)이 오면, 그 수식의 type 을 바탕
>으로 결과가 결정됩니다. 즉, sizeof 연산자는 특정 표현의 type 을 근거로
>동작합니다. 지금 하고 계신 주장은 언어 "정의"까지 부정하고 계신
>것입니다. 원하신다면 근거라도 인용해 드릴 수 있습니다.

"특정 표현의 type 을 결정해주지 못하는 것"과 "특정 표현의 type 을 근거로 동작한다는 것"은 다른 이야기 입니다. 저는 후자에 대해서는 참이라고 생각합니다. 제 주장은 sizeof(parr1) 이 배열의 크기를 return 했다고 해서, 그냥 parr1 이라는 표현이 배열은 아니라고 하는 것입니다. parr1 표현의 타입에 의해서 sizeof(parr1) 이 결정되는 것은 맞습니다. 표현에서 array 가 pointer 로 alter 되지 않는 경우가 있는데 그 중 하나가 sizeof 의 operand 로 array 타입의 표현이 들어갔을 경우입니다. 어떤 표현의 타입이 배열이고, 특정 연산자(sizeof, ++, --, &, 대입 연산자 전부에서 왼쪽, . 의 왼쪽 등)의 operand 가 아니면 포인터로 대체됩니다. 따라서 parr1 이라는 독립적인 표현은 포인터 타입입니다. parr1 이라는 표현은 항상 배열 타입이라는 주장에 대해, 독립적인 표현인 parr 이 포인터 타입이라는 사실이 반례가 된다고 생각합니다. 적어도 K&R 2nd edition 에 근거해서 생각해 봤을 때 독립적인 표현 parr1 이 포인터 타입이라는 것은 제 생각으로는 분명합니다.

----

#1

>int *parr[10];
>
>에서 *parr 이 님이 말씀하시는 선언에 포함되어 있는 "모양"입니까?
>(int *parr[10]; 은 사실 int *(parr[10]); 임에 유의하시기 바랍니다)

() 친 문장에 유의할 것 없이, *parr 빼면 int[10] -> *parr 은 배열이구나~ -> 근데 배열은 사용 시에는 포인터니까 pointer to int 로 생각해도 되겠다. 입니다. 중간 과정은 그냥 사고 과정입니다. int *parr[10] 보고 *parr 보고, 저 과정을 통해 pointer to int 라고 해도 답이 틀리지 않는 것 같다라는 이야기입니다.

>#2
>
>님의 주장대로 *parr 의 type 이 남아있는 int [10] 이고 *parr 이라는
>"사용에 의해" pointer to int 가 되는 것이라면, 그 포인터가 가리키는
>배열이 갖는 요소 개수에 대해 이야기를 해보겠습니다. 만약, 진정 *parr
>의 type 이 int [10] 이라면 *parr 이라는 사용에 의해 나타난 포인터는
>모두 10개의 int 를 가리킬 수 있어야 합니다. 그렇다면 *parr + 10 은
>선언에 의해 항상 유효한 수식입니까?

님께서 왜 제 주장에 대해서 이렇게 긴 댓글을 다시는 이해가 될 것 같습니다. 중간 사고과정은 말이 안됩니다. 처음부터 이상하다고 했구요. 모양 보고, 사용된 표현 보고, 마지막 결과의 타입이 pointer to int 겠구나 하는게 됩니다. 님께서 말씀하신 것은 애시당초 돼지님 방법으로 설명하기 힘듭니다. 오직 타입만을 결정하니까요.

int *parr[10] 에서 parr 은 'array of pointer to int' 입니다. 따라서 *parr 은 pointer to int 겠지요. 이 pointer to int 가 가르키는 것이 int[10] 라는 게 아닙니다 ;; 처음부터 그런 주장 한 적 없습니다. *parr 이 가르키는 것이 배열인지 무엇인지는 이 상황에서는 알수가 없습니다. 다만 확실한 것은 *parr에는 타입이 포인터인 숫자가 담긴다는 것 뿐이겠지요. 단지 선언 모양, 사용된 모양, 사용된 모양의 최종 타입 이것 세가지에 대해서만 저는 계속 이야기 하고 있었습니다.

>분명히 하자면, precise 하지 못한 것이 아니라 correct 하지 못했던 것
>입니다.

만약 제가 제 명제가 correct 하다고 주장했다면, "돼지님 방법으로 해도 마지막 결과 타입은 대충 맞는 것 같다"라는 명제에 대해서 correct 하다고 주장한 것인데, 저 명제가 참/거짓이 있을 수 있다고 생각하십니까? 수천개를 해서 다 맞았다고 해도 참/거짓이 결정 안나고, 명백하게 어떤 경우에 잘못된 점이 있더라도 참/거짓이 결정 안납니다. 항상 거짓인 경우에만 거짓이 되지요. 제가 처음 다시 댓글을 단 것도 전 처음부터 전웅님 주장을 incorrect 하다고 주장하지 않았을 뿐더러, 제가 쓴 것과 전웅님께서 쓴 것은 반대 논의가 아닙니다 ;; 제가 중간 과정에서 int[10]->int 배열 -> pointer to int 라고 쓴 것을 "int[10] 니까 int 배열 비스무리하게 생겼으니 사용시에는 pointer to int 겠거니~" 와 같은 뜻이라고 하면 제 의도를 아실 듯도 합니다.

> 하셨습니다.
안했습니다 ㅜㅜ

> 마지막으로 사과의 말씀 다시 드립니다.
저는 제 첫글 전웅님 주장과 배치 되지 않으므로 전혀 문제가 없을 것 같았는데 제 의도와는 완전히 다르게 되었네요. 제 첫 글은 그냥 점심시간에 이것저것 꼼지락 거리다가 진짜 가벼운 마음으로 쓴 글인데, 전웅님께서 너무 무섭게 반응하셔서 놀랐습니다. 다시 한 번 말씀드리지만 제가 주장한 바는 "~일 것 같다" 이므로, 전혀 이렇게 심각하실 필요가 없었습니다. 글 내용도 저는 그렇지 않다고 생각하지만, 글 내용에 대해서는 저렇게 긴 댓글이 있으니, 적어도 제 의도는 전혀 아니었습니다 ;;; 이 댓글에서 그 오해는 제발 풀렸으면 합니다 ;; 저도 첫 댓글을 좀 더 잘 쓰지 못해, 제 의도가 잘못 전달되서 일부러 긴 답글을 다시는데 수고하신 점에 대해서는 감사드리고 죄송합니다.

카二리의 이미지

C99 에서 VLA 가 무엇인지는 모르겠지만 정적으로 결정 된다는 말에 동의 합니다. 그런데, 변수의 타입이 정적이라고 해서, 변수를 가지고 만든 표현이 항상 같은 타입인 것은 아닙니다. 당장에 C에서 int a[10] 이란 선언 하에서, a라는 변수는 "array of int" 지만, a라는 독립적인 표현은 "pointer to int" 입니다. K&R 2nd edition 200 페이지에, 몇 가지 예외 사항을 제외하고, 어떤 표현이 배열일 때 그 표현의 배열은 포인터로 alter 된다고 나와 있습니다. C99 에서 이 부분이 바꼈을 것이라고는 생각지 않습니다. a 라는 변수가 배열이고 , a 라는 표현이 포인터라고 해서 동적 타이핑 언어가 되거나 하지 않습니다. 어차피 다 컴파일 타임에 형 결정이 날테니까요. 문법 규칙에 따라서 말이죠. 일단 전 K&R 책을 보지 않았습니다. 정확한 문장을 봐야 알겠지만 alter라는 말은 고칠수 있다는 말이지만, 같다는 말은 아닙니다. 즉 배열을 포인터로 바꿀 수 있다고 해서 배열 type을 포인터 type이라고 부를 수 없다는 겁니다. 배열과 포인터의 상관 관계에 대한 구현 방법이 C 표준에 써있는지 전 모릅니다만 만약 바꿀 수 있다고만 되어 있고 세부 구현 방법이 정의되어 있지 않다면, "말 뿐으로" type이 다른것 뿐만 아니라 내부 구현마져 완벽하게 틀리고 다만 포인터로 배열을 접근만 가능 하게 될지도 모릅니다.

ps.
전웅님은 수학자와 같이 정확한 증명을 원하시는 것 같습니다. 또한 두리뭉실 하지 않게 완벽한 정의를 내리는 것이 옳다고 생각 합니다.
wish님은 그냥 어찌저찌 하다보니 중간 과정은 좀 이상해도 대충 이렇게 된다. 하는 식으로 말씀 하시는대, 그건 제대로 모르고 있는 사람들이 오해 할 여지가 있습니다.
특히나 전웅님이 어떠한 말을 썼는대 거기에 덧 붙여서 쓰는 형식으로 써 버리셨으니 전웅님의 말을 다른 방향으로 희석해 버린게 됩니다. 전웅님께서 발끈 하신것도 무리가 아니라고 봅니다.

새 생각 :)

새 생각 :)

wish의 이미지

>일단 전 K&R 책을 보지 않았습니다. 정확한 문장을 봐야 알겠지만 alter라는 말은 고칠
>수 있다는 말이지만, 같다는 말은 아닙니다.
>즉 배열을 포인터로 바꿀 수 있다고 해서 배열 type을 포인터 type이라고 부를 수 없다
>는 겁니다.
제가 하는 주장은 같다는 것이 아닙니다. 그리고 alter는 고칠 수 있다는 것이 아니라 고친다라는 동사 아닐까요? :) 어떤 경우에 형이 alter 된다는 것은 표현이 alter 된 이후의 형으로 바뀐다는 것이죠. 그냥 인용하는 것이 나을 듯 합니다.

>> If the type of an expression or subexpression is "array of T," for some type T, then the value of the expression is a pointer to the first object in the array, and the type of the expression is altered to "pointer to T." This conversion does not take place if the expression is the operand of the unary & operator, or of ++,--, sizeof, or as the left operand of an assignment operator or the . operator. Similarly, an expression of type "function returning T," except when used as the operand of the & operator, is converted to "pointer to function returning T."

어떤 표현의 type 이 array of T 라면 몇몇 경우를 제외하고 pointer to T 로 alter 된다고 합니다. 따라서

int ip[10]

에서 ip 는 expression 이면서, 예외조건에 들어가지 않습니다. 따라서 항상 pointer to int 이므로, 그 타입은 항상 pointer to int 입니다. 이것이 제 주장이고 이것에 관해서 "대충", "~같다"라고 생각지는 않습니다. 이것은 반박되면 바로 폐기 될 수 있는 주장이죠.

>배열과 포인터의 상관 관계에 대한 구현 방법이 C 표준에 써있는지 전 모릅니다만 만약 >바꿀 수 있다고만 되어 있고 세부 구현 방법이 정의되어 있지 않다면, "말 뿐으로"
>type이 다른것 뿐만 아니라 내부 구현마져 완벽하게 틀리고 다만 포인터로 배열을 접
>근만 가능 하게 될지도 모릅니다.

일단 인용 문에서 보이 듯 바꿀 수 있는 것이 아니라 바꾸어 진다라고 되어 있습니다. 사실 이 글들 쓰면서 예전에 C 스터디 할 때 선배가 했던 말이 생각나더군요. 배열 변수는 포인터 상수와 거의 같다고 보면 "될 것 같다"고... (또 한번 이지만 "~일 것이다" 이지 "~이다" 라는 주장이 아닙니다 ㅜ_ㅜ 이거 가지고 또 배열 변수와 상수 포인터는 같지 않다! 라고 반박하면 똑같은 일이 ㅜ_ㅜ) 내부 구현이 어떻게 되었든, 언어 정의 상으로 그렇게 되어 있으니, 하는 주장입니다 :)

>전웅님은 수학자와 같이 정확한 증명을 원하시는 것 같습니다. 또한 두리뭉실 하지 않
>게 완벽한 정의를 내리는 것이 옳다고 생각 합니다.

정의에 대해서는 저도 마찬가지입니다. 저의 "돼지님의 읽는 법"에 대한 것은 정의가 아닙니다.ㅜㅜ 밑에서도 든 예이지만, "삼각형의 내각의 합은 180도 이다"와 "삼각형의 내각의 합은 180도 인 것 같다" 는 완전히 다른 이야깁니다. 앞의 이야기를 한사람한테 곡면 기하학에서 삼각형 내각의 합은 180도가 아니잖아! 라고 말하고 주장의 폐기를 요구할 수 있지만, 후자의 경우는 180도가 아닌 경우도 있네 하고 끝입니다 ㅜㅜ 후자의 사람보고 왜 180도라고 그랬냐고 비난하면 당황스럽습니다.

>wish님은 그냥 어찌저찌 하다보니 중간 과정은 좀 이상해도 대충 이렇게 된다. 하는
>식으로 말씀 하시는대, 그건 제대로 모르고 있는 사람들이 오해 할 여지가 있습니다.

된다도 아니고 되는 것 같다 입니다. 남이 오해하는 것까지 책임져야 하는 지는 잘 모르겠습니다만, 이상의 글을 다 읽은 사람이 있다면 오해할 분은 거의 없다고 생각됩니다.

>특히나 전웅님이 어떠한 말을 썼는대 거기에 덧 붙여서 쓰는 형식으로 써 버리셨으니 >전웅님의 말을 다른 방향으로 희석해 버린게 됩니다. 전웅님께서 발끈 하신것도 무리가 >아니라고 봅니다.

이 말씀은 인정하겠습니다. 애시당초 답글을 왜 달았을까 하는 생각 밖에 안듭니다. 나름대로 확실히 해야 할 개념도 논의 속에 포함 되어 있는 것 같아서 그 부분은 괜찮지만, 제 기분도 상하고 전웅님 기분도 상하신 결과를 초래한 것에 대해서는 유감스럽습니다. 그렇지만 한 가지 납득이 안가는 것이 설령 제가 어떤 분의 주장을 희석했다고 하더라도, 그렇게까지 감정적인 이야기를 들어야 했는 지는 모르겠습니다. 아니 하다 못해 그냥 짧게, "이 댓글은 틀렸네요" 라고 답글을 달았더라도, 그 정도로 감정적인 댓글을 제가 감수해야 된다고 생각 지는 않는데 말이죠.

전웅의 이미지

[...]

> >> If the type of an expression or subexpression is "array of T," for some type T,
> then the value of the expression is a pointer to the first object in the array,
> and the type of the expression is altered to "pointer to T." This conversion does
> not take place if the expression is the operand of the unary & operator, or of ++,
> --, sizeof, or as the left operand of an assignment operator or the . operator.
> Similarly, an expression of type "function returning T," except when used as the
> operand of the & operator, is converted to "pointer to function returning T."
>

앞으론 상당히 까다로운 개념적 문제를 논하면서 K&R2 를 근거로 인용
하시는 실수를 범하지 않으셨으면 좋겠습니다. 인용하신 부분에 따르면

int f(void), b;
 
b = (sizeof(f) == sizeof(&f));

에서 b 는 항상 1 (참)이어야 합니다. 하지만, 실제 그럴까요? 어떤
컴파일러는 오류를 내고 어떤 컴파일러는 0 을, 어떤 컴파일러는 1 을
주기도 할 겁니다. 님이 맹신하고 계시는 K&R2 부록의 해석을 적용하면
분명 1 이 나와야 하는데 왜 그런 결과가 나올까요? 결론은 K&R2 의 내용이
부정확하기 때문입니다 (incorrect 가 아니라 inaccurate 입니다).

노파심에 덧붙이지만, 이 답변을 보시고 또 sizeof 연산자 부분을 펼치셔서
"sizeof 연산자를 보니 함수에는 적용할 수 없다고 나와 있다" 라고
답하시지 마시길 바랍니다 - 해당 부록 전체를 직접 번역했기 때문에
어디에 무슨 내용이 있는지 거의 기억하고 있습니다.

인용하신 부분에 따르면 sizeof(f) 에서 f 는 "항상" pointer to function
으로 변환됩니다. 따라서 인용하신 부분에 따르면 sizeof(f) 는 함수에
sizeof 를 적용하는 것이 아니라 함수 포인터에 적용하는 해석이 되어야
합니다 - 물론 이는 잘못된 해석입니다.

표준의 경우, 함수 (정확히는 function designator) 의 경우 sizeof
연산자의 피연산자로 온 경우에도 포인터로 변환되지 않는다고 규정하고
있습니다. 따라서 sizeof 연산자가 함수에 적용되는 것이고, 위의 예에서
든 수식이 그 규정을 어긴 것이기 때문에 컴파일러는 에러를 내거나 자기
맘대로 행동하는 것이 가능해집니다 - 이것이 올바른 해석입니다.

[...]
>
> int ip[10]
>
> 에서 ip 는 expression 이면서, 예외조건에 들어가지 않습니다. 따라서 항상 pointer
> to int 이므로, 그 타입은 항상 pointer to int 입니다. 이것이 제 주장이고 이것에
> 관해서 "대충", "~같다"라고 생각지는 않습니다. 이것은 반박되면 바로 폐기 될 수
> 있는 주장이죠.
>

폐기하실 때가 된 것 같습니다.

[...]
> 사실 이 글들 쓰면서 예전에 C 스터디 할 때 선배가 했던 말이 생각나더군요. 배열 변수는
> 포인터 상수와 거의 같다고 보면 "될 것 같다"고... (또 한번 이지만 "~일 것이다" 이지
> "~이다" 라는 주장이 아닙니다 ㅜ_ㅜ 이거 가지고 또 배열 변수와 상수 포인터는 같지
> 않다! 라고 반박하면 똑같은 일이 ㅜ_ㅜ) 내부 구현이 어떻게 되었든, 언어 정의 상으로
> 그렇게 되어 있으니, 하는 주장입니다 :)
>

언어 정의??? K&R2 부록 따위가 언어를 정의해 주고 있다고 생각하십니까?
부록을 전부 읽어보시진 않았나 봅니다. 앞부분을 보시면 DMR 이 부록을
실으면서 "이 부록은 표준 자체가 아니다" 라는 식의 표현을 사용해 강조한
부분이 있습니다.

[... 소모적인 감정 이야기 생략]

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

카二리의 이미지

일단 alter가 동사인것 쯤은 알고 쓴겁니다.
바꾸다와 같다의 차이에 대해 말하고 싶었습니다.
나머지 부분은 전웅님이 너무 잘 설명해 주신거 같습니다.
이 스레드는 전웅님덕에 생각보다 얻어진게 많아진 스레드 같습니다.
이런 스레드는 따로 빼서 어디 모셔 놨으면 싶을 정도군요~

새 생각 :)

새 생각 :)

전웅의 이미지

원래 문맥에서 문장만 따오는 것을 정말로 경계하지만, 이번만큼은 몇몇
부분만 인용해 보겠습니다 - 그렇게 하지 않고 답글을 달면 중언부언하게
될까 걱정되어 그렇습니다.

- 전 분명히 "중간 과정은 이상해도 결과는 대충 맞는 듯 하다." 고 주장했습니다.

- 앞에서 밝혔듯이 중간과정은 이상하지만 결과는 대충 맞는다고 했습니다. 중간과정이
이상하다고 말씀드리고 시작했는데, 계속 중간과정에 대해서 말씀하시는군요.

- 제발 이제는 이 부분에 대해서 오해가 없기를 바라며, 글 자체가 모호한 것은
저도 인정합니다.

- 그냥 모양만 찾아보죠. *func 는 어째든 선언에서 보이지 않습니까? :)

- 저는 "단순히" 사용된 모양만 본 것 입니다. 진짜 단순하게요. *parr 이라는 모양은
int *parr[10]; 과 int (*parr)[10] 에 둘 다 있네요

- () 친 문장에 유의할 것 없이, *parr 빼면 int[10] -> *parr 은 배열이구나~ ->
근데 배열은 사용 시에는 포인터니까 pointer to int 로 생각해도 되겠다. 입니다.
중간 과정은 그냥 사고 과정입니다. int *parr[10] 보고 *parr 보고, 저 과정을
통해 pointer to int 라고 해도 답이 틀리지 않는 것 같다라는 이야기입니다.

- 님께서 왜 제 주장에 대해서 이렇게 긴 댓글을 다시는 이해가 될 것 같습니다.
중간 사고과정은 말이 안됩니다. 처음부터 이상하다고 했구요. 모양 보고, 사용된
표현 보고, 마지막 결과의 타입이 pointer to int 겠구나 하는게 됩니다.

- 단지 선언 모양, 사용된 모양, 사용된 모양의 최종 타입 이것 세가지에 대해서만
저는 계속 이야기 하고 있었습니다.

- 제가 그게 항상 참이라고 딱히 주장하는 것도 아니구요.

결론적으로 님께서는,

중간과정을 "대충" 때려 맞추니 말이 되는 것 "같기도" 하다. "대충"
이라고 표현했으니 중간 과정을 따지지 말고, "같기도"라고 표현했으니
항상 맞는지는 모르겠다.

라고 말씀하시고 싶으신 것이군요! 제가 느끼기에 이는 마치 오리너구리
를 보고는,

부리 모양만 "대충" 보니 오리임에 맞는 것 "같기도" 하다. 부리만 보고
말한거니 몸모양 보고 오리가 아니라고 따지지 말고 추측일 뿐이니 항상
참이라고 주장하는 것도 아니다.

라고 이야기하는 것처럼 느껴지는군요.

이렇게 해놓으시면 제가 더 이상 무슨 기술적인 말씀을 드릴 수
있겠습니까? :-( 이제 오히려 절 더 화나게 만드시는군요. 카이리님 말씀
대로 님의 말도 되지 않는 추측으로 인해 나름대로 공들여 작성한 제 글의
의도가 희석되었다는 사실만 재확인하게 됩니다. 가능한 감정적인 문제는
배제하기 위해 빨리 덮어버리려 했지만, 이제 제가 처음 감정적인 문체의
글을 작성했다는 것을 제 스스로 어느 정도 정당화할 수 있을 것
"같습니다." - 역시나 "같은" 것뿐이니 정당화되었다고 주장하는 것은
아닙니다. ;-)

사적인 이야기라면 모를까 기술적인 이야기를 나누며 "대충", "같기도"를
연발하는 분과 저는 체질적으로 맞지 않습니다. 이것만은 분명한 사실
입니다.

[...]

> 그러니까 마지막 결과물이 틀린 경우를 보여 주시면 감사하겠습니다.
> 제가 그게 항상 참이라고 딱히 주장하는 것도 아니구요. 님께서
> 주장하신 어느 부분에도 마지막 결과물이 틀린 경우는 없었습니다.

제가 보이면 또 "언제 제가 항상 참이라고 했습니까?" 라며 발뺌하실 것
아니신지요? 결국 그런 식으로 따져 나가다 보면, 다른 경우에는 다 안
맞아도 int *parr[10]; 에서 만큼은 맞지 않느냐는 억지 주장을 하실 것
아니신지요? --;

int *f(void);

에서 *f 는 님의 논리대로라면 분명 선언에 보이는 "모양"입니다. 그럼
*f 를 뺀 "int (void)" 가 "매개변수 없이 int 형을 반환하는 함수"이므로
*f 도 그런 함수가 되어야 합니다. f 의 실제 type 이 function returning
pointer to int 이고, 수식 내에서 function 은 pointer to function 으로
변환되므로 *f 는 정말로 함수가 됩니다. 그럼 반환형은 어떻게 하실
것인지요? *f 의 반환형은 pointer to int 인 반면, 남아 있는 "모양"인
"int ()" 에서의 반환형은 int 입니다. 역시나 지난번 "중간 과정을
무시한다"는 명분으로 배열 크기를 무시한 것처럼 이번에도 함수의
반환형을 애써 무시하시려 하시는지요? 하지만, 안타깝게도 배열 크기에
대한 정보는 대부분(크기에 대한 정보를 끝까지 보존해주는 구현체도
있습니다)의 구현체에서 배열이 포인터로 변환된 이후 무시되지만, 함수
반환형에 대한 정보는 그럴 수 없습니다.

전 정말이지 상식선에서 논의하고 싶습니다.

> sizeof(*parr) 에서 *parr 이나, &(*parr) 등등에서 *parr 이 포인터다 배열이다의
> 문제가 아닌 *parr 이라는 하나의 독립된 표현이 포인터 이외의 것으로 해석될 수
> 있는 지에 대한 질문입니다.
>

저 역시 위에서 *f 가 어떻게 "function returning int" 로 해석될 수
있는지에 대해 묻고 싶습니다. 님의 "대충" 논리에 따르면 "어쨌든"
함수는 함수니깐 "대충" 맞춘 셈이 되는지요? --;;;

> 어떤 표현의 타입이 배열이고, 특정 연산자(sizeof, ++, --, &, 대입 연산자
> 전부에서 왼쪽, . 의 왼쪽 등)의 operand 가 아니면 포인터로 대체됩니다.
>

아닙니다. C 언어에서 배열형의 수식은 sizeof, 단일 & 연산자, 배열
초기화시 사용되는 문자열인 경우에만 포인터로 변환되지 않습니다.
대체 어느 책에서 위와 같이 설명하고 있는지요?

솔직히 조언드리면, 님의 글만으로 판단을 내리자면 님께서는 아직 배열과
포인터의 명확한 관계를 정립하지 못하신 것 같습니다. 워낙 "대충"을
주장하시니 뭐라 설명을 드려야할지 모르겠지만, C 언어를 올바르게 이해
할 때는 상당히 핵심이 되는 부분이므로 C FAQs 같은 자료를 통해 확실히
해두시기를 강력히 추천합니다.

[sizeof 연산자에 대해서]
> "특정 표현의 type 을 결정해주지 못하는 것"과 "특정 표현의 type 을 근거로
> 동작한다는 것"은 다른 이야기 입니다.
>

대체 이 무슨 궤변이란 말입니까!

예전 typeof 도입을 논의할 때 표준에 typeof 를 추가하는 방법 중 하나로
현재 sizeof 연산자를 위해 기술된 부분을 거의 그대로 복사하고 sizeof
만을 typeof 로 바꿔쓰는 방법이 있었습니다. 그럼 typeof 역시 "특정
표현의 type 을 결정해주지는 못하고" 단지 "특정 표현의 type 을 근거로
동작하는 것" 뿐이겠군요! 일단, 저로서는 이 둘의 차이를 모르겠고,
더구나 typeof (그리고 sizeof) 가 특정 표현을 type 을 결정해주지
못한다는 궤변은 더더욱 이해하기 어렵습니다. 이 실타래는 어디서부터
풀어야할지도 모르겠습니다.

> parr1 이라는 표현은 항상 배열 타입이라는 주장에 대해, 독립적인 표현인 parr 이
> 포인터 타입이라는 사실이 반례가 된다고 생각합니다.

더 이상 C 언어 책에 투자하기 싫으시다면 인터넷 상에 공개되어 있는
C FAQs 라도 일독해 보시기를 강력 추천합니다.

> 적어도 K&R 2nd edition 에 근거해서 생각해 봤을 때 독립적인 표현
> parr1 이 포인터 타입이라는 것은 제 생각으로는 분명합니다.
[...]
> K&R 2nd edition 200 페이지에, 몇 가지 예외 사항을 제외하고, 어떤 표현이
> 배열일 때 그 표현의 배열은 포인터로 alter 된다고 나와 있습니다.

"alter" 의 뜻은 원래는 그렇지 않았던 것이 변질된다는 의미입니다.
특히 의미상으로 "성질"등의 고유 특성이 변함을 강조할 때 사용되는
단어입니다. 즉, K&R 에서도 "배열"과 "포인터"가 분명 다르며, 단지
일정 문맥에서 포인터로 "변질된다는" 것을 잘 표현하고 있는 것입니다.

> 님의 감정 상태를 제가 알 필요는 없습니다. 제가 감정이 상했다면 [...]

님이 제 감정 상태를 알 필요가 없는데, 왜 저는 알아야 할까요? 님의
저 한 문장으로 제가 이전 글들에서 괜히 사과했다는 생각이 드는군요.

제가 왜 그토록 감정적인 문체의 표현을 사용했는지는 오히려 카이리님이
잘 설명해 주셨습니다. 감정적인 문제에 대한 이야기는 별로 배울 것이
없어 사과 드리는 것으로 마무리하고 기술적인 토론으로 화제를 옮기려
했습니다. 하지만, 님의 "대충", "같기도" 논리 앞에서는 불가능해
보이는군요.

참/거짓이 분명한 문제입니다. 님께서 굳이 "대충" 논리로 그 경계를
불분명하게 만들고 싶으시다면 (워낙 고집이 있으시니) 저는 더 이상
관여하지 않겠습니다. 하지만, 제발 (제 글이 아닌) 다른 곳에서 하시기
바랍니다. 제가 유아기적 결벽증을 가지고 있는 것인지 모르겠지만,
도저히 아닌 것을 맞다고 말씀드릴 수는 없습니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

>제가 보이면 또 "언제 제가 항상 참이라고 했습니까?" 라며 발뺌하실 것
>아니신지요? 결국 그런 식으로 따져 나가다 보면, 다른 경우에는 다 안
>맞아도 int *parr[10]; 에서 만큼은 맞지 않느냐는 억지 주장을 하실 것
>아니신지요? --;

맞습니다 ;;

>int *f(void);
일단 이 모양은 function returning pointer to int 군요.

>에서 *f 는 님의 논리대로라면 분명 선언에 보이는 "모양"입니다. 그럼
>*f 를 뺀 "int (void)" 가 "매개변수 없이 int 형을 반환하는 함수"이므로
>*f 도 그런 함수가 되어야 합니다.
그렇군요

>f 의 실제 type 이 function returning
>pointer to int 이고, 수식 내에서 function 은 pointer to function 으로
>변환되므로 *f 는 정말로 함수가 됩니다. 그럼 반환형은 어떻게 하실
>것인지요? *f 의 반환형은 pointer to int 인 반면, 남아 있는 "모양"인
>"int ()" 에서의 반환형은 int 입니다. 역시나 지난번 "중간 과정을
>무시한다"는 명분으로 배열 크기를 무시한 것처럼 이번에도 함수의
>반환형을 애써 무시하시려 하시는지요? 하지만, 안타깝게도 배열 크기에
>대한 정보는 대부분(크기에 대한 정보를 끝까지 보존해주는 구현체도
>있습니다)의 구현체에서 배열이 포인터로 변환된 이후 무시되지만, 함수
>반환형에 대한 정보는 그럴 수 없습니다.

안맞네요 ^^ 이런 간단한 것을 안해보다니 ;; 해보긴 했는데 변화 형에 대해서 신경을 안썼군요. 반례가 있으니 이제 저 방법은 안 맞을 때도 있다는 것을 알았네요. 감사하고 지금까지 그 부분에 대해서 주장한 것에 대해서 사과드리겠습니다.

>아닙니다. C 언어에서 배열형의 수식은 sizeof, 단일 & 연산자, 배열
>초기화시 사용되는 문자열인 경우에만 포인터로 변환되지 않습니다.
>대체 어느 책에서 위와 같이 설명하고 있는지요?

K&R 2nd ed. 200 page A.7 을 보시기 바랍니다
The C Programming Language 2nd edition 을 말하는 겁니다.
나온 문장 그대로 번역했습니다. C 만든 사람들이 쓴 책인데 정당한 reference라고 생각합니다만. 그리고 상식적으로도 대입 연산자의 왼쪽에서 배열이 포인터로 변하면 여러 애매한 문제가 발생하지 않나요?

int a[10];
int b[10];

에서

a = b;

라는 표현이 만약 a가 포인터로 변한다면 아무 문제가 없어야 하는데, 분명히 씨에서 허용되지 않는 표현이죠. 물론 a 가 상수 포인터로 변하기 때문에 안된다고 볼 수도 있겠습니다만...

>대체 이 무슨 궤변이란 말입니까!
>
>예전 typeof 도입을 논의할 때 표준에 typeof 를 추가하는 방법 중 하나로
>현재 sizeof 연산자를 위해 기술된 부분을 거의 그대로 복사하고 sizeof
>만을 typeof 로 바꿔쓰는 방법이 있었습니다. 그럼 typeof 역시 "특정
>표현의 type 을 결정해주지는 못하고" 단지 "특정 표현의 type 을 근거로
>동작하는 것" 뿐이겠군요! 일단, 저로서는 이 둘의 차이를 모르겠고,
>더구나 typeof (그리고 sizeof) 가 특정 표현을 type 을 결정해주지
>못한다는 궤변은 더더욱 이해하기 어렵습니다. 이 실타래는 어디서부터
>풀어야할지도 모르겠습니다.

제발... 제 글이 먼저 "틀렸다"고 생각지 마시고 한번 읽어주시기 바랍니다.

int ip[10]; 에서

sizeof(ip)에서의 ip와 단독으로 쓰였을 때의 ip가 같은 타입인지 C grammar 를 한번 쭉 따라가보셨으면 합니다. ip가 단독으로 expression 으로 쓰이면 이 expression 의 type 은 pointer to int 입니다. 예를 들어 if( ip ) 이런식으로 쓰였을 때 ip 의 타입은 pointer to int 이지 array of int 가 "아닙니다". 근거로 K&R 2nd ed. 그라마 정의 부분과 위에서 언급한 부분을 제시합니다.

>> parr1 이라는 표현은 항상 배열 타입이라는 주장에 대해, 독립적인 표현인 parr 이
>> 포인터 타입이라는 사실이 반례가 된다고 생각합니다.
>더 이상 C 언어 책에 투자하기 싫으시다면 인터넷 상에 공개되어 있는
>C FAQs 라도 일독해 보시기를 강력 추천합니다.

이 질문만 드려 보지요. if(parr) 에서 parr라는 표현이 포인터 타입이 아닌가요? 아니면 expression 이 evaluate 된 이후에 포인터로 형 변환 되었다고 생각하는 건가요?

>"alter" 의 뜻은 원래는 그렇지 않았던 것이 변질된다는 의미입니다.
>특히 의미상으로 "성질"등의 고유 특성이 변함을 강조할 때 사용되는
>단어입니다.

예 맞습니다. 변화 했으니 그 표현의 형은 변화 후의 것을 취해야 되는 것 아닌지요? ;;

> 즉, K&R 에서도 "배열"과 "포인터"가 분명 다르며, 단지
>일정 문맥에서 포인터로 "변질된다는" 것을 잘 표현하고 있는 것입니다

배열하고 포인터가 같다고 한적 전혀 없습니다만 ;;

>감정적인 문제에 대한 이야기는 별로 배울 것이
>없어 사과 드리는 것으로 마무리하고 기술적인 토론으로 화제를 옮기려
>했습니다. 하지만, 님의 "대충", "같기도" 논리 앞에서는 불가능해
>보이는군요.

대충과 같기도는 논리가 아닙니다. 따라서 처음 표기를 읽는 방법 자체는 논리적인 것이 아니라고 말씀드렸습니다. 기술적인 것은 당연히 논리적입니다. 저는 논리적인 것에 관해서는 대충, 같기도를 붙이는 것을 극단적으로 싫어하는 사람 중 한명입니다. 만약 제가 그런 표현을 논리의 세계에 썼다면 지적해 주시면 정말 감사하겠습니다.

>참/거짓이 분명한 문제입니다. 님께서 굳이 "대충" 논리로 그 경계를
>불분명하게 만들고 싶으시다면 (워낙 고집이 있으시니) 저는 더 이상
>관여하지 않겠습니다. 하지만, 제발 (제 글이 아닌) 다른 곳에서 하시기
>바랍니다. 제가 유아기적 결벽증을 가지고 있는 것인지 모르겠지만,
>도저히 아닌 것을 맞다고 말씀드릴 수는 없습니다

역시 저를 오해하고 계시는군요 :)

"삼각형의 내각의 합은 180이다" 는 참/거짓이 있습니다. 필연적 참이죠. (좀 더 정확하게는 유클리드 기하학에서 ;; 머 하나 쓰기가 겁이 나는군요 ;;)
"삼각형의 내각의 합은 180도 인 것 같다"가 참/거짓이 있습니까? 필연적 참은 물론이거니와 우연적 참/거짓도 결론 내리지 못합니다. 추측일 뿐이기 때문이죠.

앞에서 쓰고 쓰고 또 썼지만, 제가 참 or 거짓을 주장하지 않았는데, 제가 마치 참을 주장한 것으로 규정하시고, 그것이 거짓이다라고 말씀하신 것은 전웅님이십니다. 처음에 전웅님께서 이 댓글에서 제시한 예를 달았으면 저는 반례가 있다고 인정했을 것입니다. 이번 댓글에서 인정했지요. 그렇다고 해서 제가 한 처음 주장을 철회활 필요는 없습니다. 왜냐하면 제가 처음 한 주장 자체가 참/거짓이 있을 수가 없기 때문입니다.

물론 ~인 것 같다는 주장은 "읽는 법"에 한해서 입니다. 포인터와 배열 형에 대한 문제는 참/거짓이 분명한 주장이니 얼마든지 틀렸다고 말씀하셔도 좋고 제가 잘못 알고 있었다면 거짓임을 인정할 용의도 얼마든지 있습니다. 다만 현재 전웅님께서 하시는 한 표현의 형이 고정되어 있다는 주장은 분명히 거짓이라고 생각합니다. 이유는 위에서 제시한 대로 이구요.

변수명 단독으로 쓰는 것은 분명히 expression 이고 expression 의 최종형이 array of 로 나왔을 때는 항상 pointer to 형으로 변화한다. 그리고 이 변화는 실행 중에 일어나는 타입 캐스팅과는 다른 문제이고 컴파일 타임에서 다 결정난다. 그러므로 하나의 표현에 대한 형이 고정되어 있다고 볼 수 없다는 것이 제 주장입니다. 그리고 처음 "돼지님의 읽는 방법"은 맞지 않는 경우가 있다는 주장은 받아들입니다. 많은 반례를 다 해 보지 않고 반례가 없는 것 같다고 주장한 것에 대해서는 사과하겠습니다.

lovewar의 이미지

>>변수명 단독으로 쓰는 것은 분명히 expression 이고 expression 의 최종형이 array of 로 나왔을 때는 항상 pointer to 형으로 변화한다.
프로그래밍 언어를 정의하는 측면과 구현하는 측면에서 정의하는 측면을 봐야 할것 같습니다. 정의 측면은 대략 비슷해지긴 하지만 항상 같지는 않을겁니다.

wish의 이미지

음... 말씀이 조금 복잡하셔서 ^^;

int ip[10];

에서

"프로그래밍 언어를 정의하는 측면" 에서 ip 라는 표현은 배열 형이지만,
"프로그래밍 언어를 구현하는 측면에서 정의하는 측면"에서 ip 라는 표현은 포인터 형이라는 의미로 말씀하신 것인가요?

저에게는 조금 애매하게 다가오네요 ^^

lovewar의 이미지

>>프로그래밍 언어를 정의하는 측면과 구현하는 측면에서 정의하는 측면을 봐야 할것 같습니다. 정의 측면은 대략 비슷해지긴 하지만 항상 같지는 않을겁니다.

"프로그래밍 언어를 정의하는 측면과 구현하는 측면중에서 정의하는 측면으로 봐야 할것 같습니다. 그리고 프로그래밍 언어를 구현하는 측면(컴파일러들)은 대략 비슷해지긴 하지만 항상 같지는 않을겁니다." 란 글이었습니다.

-- 덧붙이는 글 --
제 글 자체가 혼동이었군요. 죄송합니다. 꾸벅..

lovewar의 이미지

유사하게 다음 예제도 한번 고민해 보시기 바랍니다:

int main(void) {
    struct Header structHeaderVariable;
    /* do something */
 
    structHeaderVariable;  /* 유사하게 생각되는 것을 예제로 담았습니다. */
 
    return 0;
}

프로그래밍 언의의 정의측면에서 정해지지(?, 배열및 사용자 정의자료형) 않는 크기를 갖는type들 대부분은 구현측면(컴파일러)에서
번지의 조작기법이 적용될 거라 생각합니다.
그렇다고 그것의 자료형을 바꿔 인식하는 것은 좋지 않습니다.
달리 부가적인 설명은 필요하지 않을것 같습니다.

-- 덧 붙이는 글 --
위 예제는 표준 문서의 내용과 관계가 없는 예제입니다.

전웅의 이미지

> >제가 보이면 또 "언제 제가 항상 참이라고 했습니까?" 라며 발뺌하실 것
> >아니신지요? 결국 그런 식으로 따져 나가다 보면, 다른 경우에는 다 안
> >맞아도 int *parr[10]; 에서 만큼은 맞지 않느냐는 억지 주장을 하실 것
> >아니신지요? --;
>
> 맞습니다 ;;
>

죄송하지만, 이런 말장난을 해드리기에는 제가 그리 시간적 여유가 많지
않습니다.

[int *f(void); 를 사용한 설명 생략]
>
> 안맞네요 ^^ 이런 간단한 것을 안해보다니 ;; 해보긴 했는데 변화 형에 대해서
> 신경을 안썼군요. 반례가 있으니 이제 저 방법은 안 맞을 때도 있다는 것을 알았네요.
> 감사하고 지금까지 그 부분에 대해서 주장한 것에 대해서 사과드리겠습니다.
>

"안 맞을 때도 있다..."

어떤 규칙은 모든 경우에 예외 없이 적용 가능합니다. 다른 규칙은 99% 가
예외이며 나머지 1% 만이 적용 가능합니다. 이와 같은 상황에서 님은
후자를 선택하신 것입니다. 억지도 어지간히 부리시기 바랍니다. 서서히
님과 이런 글을 주고 받는 다는 것 자체가 부끄러워지기 시작했습니다.

솔직히 저렇게 단순한 반례를 찾지 못해 그와 같은 주장을 고집하시는
것이라고는 생각하지 못했습니다. 처음 이 글을 시작할 때 제기된 문제는
충분히 정리되었으니 더 이상 이야기 나눌 것이 없으리라 생각합니다.
아래에 언급하신 부분만 설명드리겠습니다.

(개인적으로 10년이라는 시간동안 각종 게시판, 뉴스그룹 등에서 이야기를
나누다보면, 아예 아무 것도 모르는 분들에게 올바른 지식을 전달하기는
상대적으로 쉽습니다. 가장 어려운 경우가 올바르지 않은 지식을 맹신하며
끝까지 고집하는 분들입니다. 한번만 더 설명을 드리겠습니다. 이해가 되지
않는 부분은 "질문"을 하시기 바랍니다. 님의 고집스럽도록 잘못된 지식을
계속 고쳐드리기엔 너무 지쳤습니다 - 솔직히 기분도 내키지 않는 상태에서
님께 답변 드려서 제가 얻는 것이 아무 것도 없습니다, 게시판을
지저분하게 만든다는 죄책감만 늘어날 뿐입니다.

> >아닙니다. C 언어에서 배열형의 수식은 sizeof, 단일 & 연산자, 배열
> >초기화시 사용되는 문자열인 경우에만 포인터로 변환되지 않습니다.
> >대체 어느 책에서 위와 같이 설명하고 있는지요?
>
> K&R 2nd ed. 200 page A.7 을 보시기 바랍니다
> The C Programming Language 2nd edition 을 말하는 겁니다.
>

구글에서 "K&R2 Reference Manual 번역본" 을 검색해 보시기 바랍니다.
제가 7년 전 말씀하신 책의 부록을 번역해 인터넷을 통해 공개한 것입니다.
지금부터 님이 해당 부록에 대해 잘못 알고 계신 부분을 알려드리겠습니다.

>
> 나온 문장 그대로 번역했습니다. C 만든 사람들이 쓴 책인데 정당한
> reference라고 생각합니다만.

K&R2 는 Dennis Ritchie 와 Brian Kernighan 이 쓴 책으로 알려져
있습니다. C 를 만든 사람"들"이라고 표현하시는데, C 언어는 Dennis
Ritchie 가 만들었습니다. BWK 는 주로 K&R2 의 본문인 tutorial 부분을
집필했으며, DMR 은 부록을 정리했습니다.

K&R2 의 부록A 는 앞부분에도 나와 있지만, 당시의 ANSI 표준 초안을
바탕으로 요약본을 만든 것입니다. 이 정도 사실은 알고 "정당한
reference" 라는 표현을 쓰시는지 모르겠습니다.

C 언어의 "마지막 권위"는 표준입니다. 님이 사용하는 컴파일러도, (K&R2
은 물론 제 책을 포함해) C 언어를 쉽게 익힐 수 있도록 출판된 책도 C
언어의 정의를 제공하는 것은 아닙니다.

K&R2 의 부록A 는 표준 초안을 바탕으로 하고 있고, 방대한 양을 적은
양으로 요약하는 과정에서 잘못된 부분, 불명확한 부분이 상당히 많습니다.
C 언어의 전체적 모습을 파악하기는 좋지만, 세세한 부분까지 올바른 해석
을 제공하지는 않습니다.

해당 부분에서 K&R2 는 modifiable lvalue 와 lvalue 의 구분 같은 보다
상세한 개념을 도입하지 않기 위해 그럴싸한 방법으로 표준을
옮겨놓았습니다.

> 그리고 상식적으로도 대입 연산자의 왼쪽에서 배열이 포인터로 변하면 여러 애매한
> 문제가 발생하지 않나요?
>
> int a[10];
> int b[10];
>
> 에서
>
> a = b;
>
> 라는 표현이 만약 a가 포인터로 변한다면 아무 문제가 없어야 하는데,
> 분명히 씨에서 허용되지 않는 표현이죠. 물론 a 가 상수 포인터로 변하기 때문에
> 안된다고 볼 수도 있겠습니다만...

이와 관련된 내용은 이곳 게시판과 hclc 등에 무수히 포스팅한 적
있습니다.

대입 연산자의 좌측 피연산자는 기본적으로 lvalue 보다 더 제한된 특성을
갖는 modifiable lvalue 여야 합니다. 대입 연산자의 좌측 피연산자로
array type 이 온 경우 포인터로 변환됩니다. 정의에 의해 배열이 포인터로
변환될 경우 (modifiable lvalue 는 커녕) lvalue 도 될 수 없기 때문에
대입 연산자의 좌측 피연산자로는 허락되지 않는 것입니다.

이것이 표준에 의한 해석입니다. 표준이 도입해 적용하고 있는 개념과
규칙은 매우 논리적이기 때문에 언어 전 부분에 일관되게 적용될 수
있습니다.

K&R2 부록에서 주어진 설명은 보다 세세한 개념을 도입하지 않으면서도
동일한 결론을 얻을 수 있도록 쉽게 설명했다고 보시면 됩니다. 하지만,
그와 같은 개념 구성은 표준에서처럼 언어 전 부분에 일관되게 적용될 수
없는 말 그대로 "대강"의 개념입니다.

[...]

> 제발... 제 글이 먼저 "틀렸다"고 생각지 마시고 한번 읽어주시기 바랍니다.
>
> int ip[10]; 에서
>
> sizeof(ip)에서의 ip와 단독으로 쓰였을 때의 ip가 같은 타입인지 C grammar 를 한번
> 쭉 따라가보셨으면 합니다. ip가 단독으로 expression 으로 쓰이면 이 expression 의
> type 은 pointer to int 입니다. 예를 들어 if( ip ) 이런식으로 쓰였을 때 ip 의
> 타입은 pointer to int 이지 array of int 가 "아닙니다". 근거로 K&R 2nd ed. 그라마
> 정의 부분과 위에서 언급한 부분을 제시합니다.
>

대체 왜 문법을 들먹이시는지 모르겠습니다. --;;; 차라리 모르시면 질문을
하십시오. 정말 답답해 죽겠습니다.

type 은 semantic 요소입니다. 이것이 어떻게 syntactic 요소와 관련이
있다고 주장을 하시는지요. 지금 님께서 주장하고 계신 것은 비유로
말씀드리면,

- "아!" 라는 단어가 문장 가장 앞에 왔기 때문에 감정을 표현하는 것이다

라고 주장하시는 것과 다르지 않습니다 - "문장의 가장 앞" 이 문법적
요소라면 "감정을 표현한다"는 것은 "아!" 라는 단어의 의미적 요소입니다.

ip 가 단독으로 쓰일 경우 type 은 arrray 입니다. 수식을 평가하는
과정에서 첫 요소를 가리키는 포인터로 변환되는 것입니다. 이것이 언어를
올바르게 이해하는 방법입니다. C 언어에서 type 이 정적이라는 것은
"정적으로 type 을 결정할 수 있다"는 것을 의미하지, "개념상 최종적으로
변환된 type 을 갖는 것으로 보아야 한다"는 것을 의미하는 것이 아닙니다.

예를 들어, 비원형 함수 호출 수식에서 모든 인자에는 기본 인자 진급
(default argument promotion) 이 적용됩니다. 마치 배열이 여러 문맥에서
포인터로 변환되듯이 이때 float 형은 double 형으로 변환됩니다.

int f();   /* non-proto type */
float v;
 
f(v);

이 때 f(v) 에서 v 의 type 이 무엇이냐고 물으면 "double" 이라고
답하시겠습니까?

님이 수식(expression) ip 의 type 이 포인터라고 주장하는 것은 v 가
double 이라고 주장하는 것과 다르지 않습니다.

다시 한번 말씀드리지만, ip 의 type 은 array 입니다. ip 라는 수식을
평가하는 과정에서 언어 규칙에 의해 포인터로 변환되는 것입니다. 이는
매우 중요한 언어적 개념입니다.

>
> 이 질문만 드려 보지요. if(parr) 에서 parr라는 표현이 포인터 타입이 아닌가요?
> 아니면 expression 이 evaluate 된 이후에 포인터로 형 변환 되었다고 생각하는
> 건가요?
>

님이 주장하시는 내용을 보았을 때 질문을 하나만 하셔서는 안 될 것
같습니다. 주신 질문에 답변을 드리자면, 수식을 평가하면서 포인터로
변환하게 됩니다.

> >"alter" 의 뜻은 원래는 그렇지 않았던 것이 변질된다는 의미입니다.
> >특히 의미상으로 "성질"등의 고유 특성이 변함을 강조할 때 사용되는
> >단어입니다.
>
> 예 맞습니다. 변화 했으니 그 표현의 형은 변화 후의 것을 취해야 되는 것 아닌지요? ;;
>

위에서 다른 예를 들어 그렇지 않다는 것을 말씀드렸습니다.

[...]
>
> 대충과 같기도는 논리가 아닙니다. 따라서 처음 표기를 읽는 방법 자체는 논리적인
> 것이 아니라고 말씀드렸습니다. 기술적인 것은 당연히 논리적입니다. 저는 논리적인
> 것에 관해서는 대충, 같기도를 붙이는 것을 극단적으로 싫어하는 사람 중 한명입니다.
> 만약 제가 그런 표현을 논리의 세계에 썼다면 지적해 주시면 정말 감사하겠습니다.
>
[...]
>
> 역시 저를 오해하고 계시는군요 :)
>
> "삼각형의 내각의 합은 180이다" 는 참/거짓이 있습니다. 필연적 참이죠. (좀 더 정확하게는
> 유클리드 기하학에서 ;; 머 하나 쓰기가 겁이 나는군요 ;;)
> "삼각형의 내각의 합은 180도 인 것 같다"가 참/거짓이 있습니까? 필연적 참은 물론이거니와
> 우연적 참/거짓도 결론 내리지 못합니다. 추측일 뿐이기 때문이죠.
>
> 앞에서 쓰고 쓰고 또 썼지만, 제가 참 or 거짓을 주장하지 않았는데, 제가 마치 참을
> 주장한 것으로 규정하시고, 그것이 거짓이다라고 말씀하신 것은 전웅님이십니다. 처음에
> 전웅님께서 이 댓글에서 제시한 예를 달았으면 저는 반례가 있다고 인정했을 것입니다.
> 이번 댓글에서 인정했지요. 그렇다고 해서 제가 한 처음 주장을 철회활 필요는 없습니다.
> 왜냐하면 제가 처음 한 주장 자체가 참/거짓이 있을 수가 없기 때문입니다.
>

네, 알겠습니다. 그럼, 다음부터 독립된 답글을 달지언정 제 답글에는
논리적 주장의 탈을 쓴 추측은 달지 말아 주시기 바랍니다. 님도 동감
하시겠지만, 또 한번 소모적이며 지리한 논쟁을 하고 싶지는 않습니다.

> 물론 ~인 것 같다는 주장은 "읽는 법"에 한해서 입니다. 포인터와 배열 형에 대한 문제는
> 참/거짓이 분명한 주장이니 얼마든지 틀렸다고 말씀하셔도 좋고 제가 잘못 알고 있었다면
> 거짓임을 인정할 용의도 얼마든지 있습니다. 다만 현재 전웅님께서 하시는 한 표현의 형이
> 고정되어 있다는 주장은 분명히 거짓이라고 생각합니다. 이유는 위에서 제시한 대로 이구요.
>

제가 위에서 님께 드린 설명은 제가 님처럼 책 한권에서 본 내용을
어설프게 구성해 전달하는 것이 아닙니다. 수년간 같은 내용을 놓고 책에서
보고, 표준에서 보고, 책으로 쓰고, 뉴스그룹이나 메일을 통해 표준
위원회 위원을 포함한 다양한 사람들과 논의한 결과로 얻게 된 것입니다.
함부로 "거짓"이라 부를 종류의 것이 아닙니다.

> 변수명 단독으로 쓰는 것은 분명히 expression 이고 expression 의 최종형이 array of 로
> 나왔을 때는 항상 pointer to 형으로 변화한다. 그리고 이 변화는 실행 중에 일어나는 타입
> 캐스팅과는 다른 문제이고 컴파일 타임에서 다 결정난다. 그러므로 하나의 표현에 대한 형이
> 고정되어 있다고 볼 수 없다는 것이 제 주장입니다.

아.. 바로 이것입니다. 드디어 님의 오해가 시작된 부분을 찾았습니다.
C 언어는 "실행시 변환", "컴파일시 변환" 같은 개념을 가지고 있지
않습니다. 실행 중 타입 캐스팅에 의해 일어나는 변환과 배열이 포인터로
변환되는 변환은 모두 그냥 "변환"일 뿐입니다. 차이가 있다면 하나는
명시적인 변환이고, 다른 하나는 암시적 변환이라는 것 뿐입니다.

이미 설명드렸듯이, "모든 type 은 컴파일시에 결정난다" 는 것은
프로그램의 "실행"없이 소스 텍스트를 "읽는" 것만으로도 type 을 결정할
수 있다는 뜻입니다. 예를 들어, 님께서 "실행 중에" 일어난다고 표현하신
캐스팅의 경우에도 소스 텍스트만을 보고 정적으로 변환된 결과를 알 수
있음을 의미합니다. 반면,

void func(int n)
{
    int a[n];
    ...

과 같은 VLA 는 a 의 type 을 번역시에 결정할 수 없습니다. n 으로 전달
되는 값을 실행해보지 않고는 알 수 없기 때문입니다 - 말씀드렸듯이
배열이라는 type 의 특성을 결정짓는 요소에는 개수도 포함됩니다, 예를
들면 int [10] 과 int [1] 은 크기 때문에 호환되지 않는 type 입니다.

캐스트를 사용한 강제 형변환이든, 배열이 포인터로 암시적으로 변환되는
것이든 "개념상" 해당 수식을 평가하면서 이루어진다고 보셔야 합니다.

예를 들어 보겠습니다.

short int a;
 
switch(a)
{
   ...

이 경우 switch 문의 control expression 에는 "암시적"으로 intergral
promotion 이 적용됩니다. 즉, short int 형의 값을 int 형으로 변환한
후에 case 와 비교에 의한 jump 를 수행하게 됩니다.

if (ip) 에서 님 말씀대로 ip 에 배열 -> 포인터로의 암시적 변환이
일어난다고 해서 수식 ip 의 type 을 무조건 포인터라고 보아야 한다면,
위와 같은 switch 문에서 a 의 type 은 무조건 int 라고 보아야 합니다
(혹은 short int 와 int 가 동일한 표현 범위를 갖는 경우 unsigned int
로 변환되므로 unsigned int 라고 보아야 합니다). 이것은 올바른 해석이
될 수 없습니다.

(lovewar 님이 말씀하신 내용을 부연하자면) 물론, 실제 컴파일러 구현시
특정 형변환이 실제 목적 코드로 생성될 필요가 없는 경우나, 목적 코드
생성시 미리 변화된 값이 생성되도록 할 수도 있습니다. 이는 어디까지나
"구현"의 측면이지 언어를 이해하는 "개념"적 측면이 아닙니다. 개념적
으로는 if (ip) 에서나 switch(a) 에서나 수식 평가가 일어나면서 변환이
적용되는 것이 맞는 해석 방법입니다.

님이 변환에 대해 오해하고 계신 원인을 알게 되었으니 이 정도면 충분히
설명이 되지 않았나 생각합니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

먼저 감사하다는 말씀을 드리겠습니다. 댓글 달면서 많은 것을 알게 됐네요. 전웅님께서 얻는 것이 거의 없으셨다는 것이 유감스럽지만요. 그리고 이상한 댓글에 시간 낭비하게 만드신 것에 대해서 사과드리겠습니다. 솔직히 전웅님이 이 분야에 대해 깊게 알고 계신다는 것은 예전 글에서부터 많이 느껴왔습니다. 다만 제가 좀 많이 잘못했더라도 왜 이런 말투를 들어야 하는가에 대해서는 아직도 의문스럽습니다. 이번 댓글도 마찬가지구요. 저도 기왕에 댓글 달 거 감정적으로 달았어야 하는 걸까 의문이 들기 시작했습니다. 혹 제가 전웅님께 조금이라도 감정적으로 대했던 적이 있었는 지가 궁금하네요.

포인터와 배열에 대한 것은 제가 전웅님 이번 댓글을 보니 그냥 어떻게 보느냐의 차이인 것 같습니다. 왠지 또 이것 때문에 한소리 들을 것 같아서 무섭습니다만 ;;

int ip[10];
ip;

라면, 여기서 ip 라는 표현은 evaluate 되기 전에는 배열이었다가 evaluate 되면서 포인터로 바뀐다는 것이라고 하셨는데, 제가 ip 라는 표현이 포인터 타입이라고 주장했던 것은, 저런 구문에서 최종적으로 ip 는 항상 포인터 타입이라는 뜻이었습니다. 전웅님께서 저 ip라는 표현이 배열이라고 주장하시는 것으로 생각했습니다만 그것은 아닌것 같네요. 제가 sizeof(ip) 의 크기가 ip 의 타입을 결정내리지 못한다는 것도, 저 코드에서 ip 라는 표현의 타입은 최종적으로 포인터인데 sizeof(ip) 는 배열 크기를 보여 주어서 입니다. if(ip) 의 경우도 최종적으로 ip 라는 표현이 포인터 타입이라는 뜻이었습니다. 혹여 저 코드에서 ip 의 타입이 최종적으로도 배열이라고 하신다면 그것은 또 제가 잘못 알고 있는 것이겠지요.

게시판 댓글 창 어지럽힌 점에 대해서 혹시라도 이 글을 보실 모든 분께 사과드리겠습니다.

전웅의 이미지

> 먼저 감사하다는 말씀을 드리겠습니다. 댓글 달면서 많은 것을 알게 됐네요.
> 전웅님께서 얻는 것이 거의 없으셨다는 것이 유감스럽지만요. 그리고 이상한 댓글에
> 시간 낭비하게 만드신 것에 대해서 사과드리겠습니다. 솔직히 전웅님이 이 분야에
> 대해 깊게 알고 계신다는 것은 예전 글에서부터 많이 느껴왔습니다. 다만 제가 좀
> 많이 잘못했더라도 왜 이런 말투를 들어야 하는가에 대해서는 아직도 의문스럽습니다.
> 이번 댓글도 마찬가지구요. 저도 기왕에 댓글 달 거 감정적으로 달았어야 하는 걸까
> 의문이 들기 시작했습니다. 혹 제가 전웅님께 조금이라도 감정적으로 대했던 적이
> 있었는 지가 궁금하네요.
>

직설적으로 감정적 표현을 사용하는 것만이 상대방의 감정을 불편하게
만드는 일이라 생각하시면 곤란합니다. 제가 인격적으로 덜 성숙한 탓에
정도 이상으로 민감하게 반응한 부분이 없지 않다는 것은 이미 인정한
사실입니다. 하지만 일련의 글을 통해 님이 보여주신 행동들은 그런 제
감정을 불편하게 만들기에 충분했습니다. 불 구경, 싸움 구경은 돈 주고도
못한다고 하지만, 이런 감정 싸움이 이 글을 보시는 다른 분들에게는 물론
서로에게도 득될 것이 없기 때문에 더 이상의 이야기는 하지 않겠습니다.
이런 이유로 줄곧 감정 문제를 피해왔음에도 집요하게 언급하시는 것을
보니 제게 화가 많이 나신 것 같습니다. 혼자서 풀 수 없으시다면 차라리
메일을 주시기 바랍니다. 그렇지 않아도 지저분해진 게시판에 더러움으로
일조하고 싶진 않습니다.

> 포인터와 배열에 대한 것은 제가 전웅님 이번 댓글을 보니 그냥 어떻게 보느냐의
> 차이인 것 같습니다. 왠지 또 이것 때문에 한소리 들을 것 같아서 무섭습니다만 ;;
>

저는 님이 제가 드리는 잔소리에 지쳐 님이 이해하고 있는 방식을 바꾸길
바라는게 아닙니다. 이해를 통해 진정 저와 같은 개념을 갖게 되시기를
바라고 있는 것입니다. 같은 현상을 바라보는 다양한 방식이 있지만, 지금
다루고 있는 주제는 창조론/진화론처럼 서로 전혀 다른 관점이 존재할만큼
논란의 여지가 큰 주제가 아닙니다. (저 역시 배운 내용이긴 하지만) 제가
가지고 있는 개념이 상당히 효율적이며, 또한 대부분의 사람들이 공유하고
있는 방식이기에 나누고자 하는 것뿐입니다.

> int ip[10];
> ip;
>
> 라면, 여기서 ip 라는 표현은 evaluate 되기 전에는 배열이었다가 evaluate 되면서
> 포인터로 바뀐다는 것이라고 하셨는데, 제가 ip 라는 표현이 포인터 타입이라고
> 주장했던 것은, 저런 구문에서 최종적으로 ip 는 항상 포인터 타입이라는 뜻이었습니다.
> 전웅님께서 저 ip라는 표현이 배열이라고 주장하시는 것으로 생각했습니다만 그것은
> 아닌것 같네요. 제가 sizeof(ip) 의 크기가 ip 의 타입을 결정내리지 못한다는 것도,
> 저 코드에서 ip 라는 표현의 타입은 최종적으로 포인터인데 sizeof(ip) 는 배열
> 크기를 보여 주어서 입니다.
>

ip; 라는 수식이 평가 후 갖는 type 이 포인터라는 사실에는 이의가
없습니다. 하지만, 그 수식에서 평가를 통해 ip 가 갖는 type 이 결국엔
포인터이기에 sizeof(ip) 가 ip 의 올바른 type 을 보여주지 못한다는
주장까지 닿을 수는 없습니다.

비유를 해보겠습니다. 어떤 마을 한 소년은 생김새도 워낙 이쁘장하고
여자 옷 입는 것을 좋아해 거의 항상 누나 옷을 몰래 입고 마을을
돌아다녔습니다. 워낙 잘 어울려 누나 옷을 입고 다니는 동안에는 아무도
그 아이를 사내아이라 생각하지 못했습니다. 다만, 너무도 엄한 부모님
앞에서는 혼이 날까 두려워 그 누구보다도 사내다운 모습을 보이려
노력했습니다.

그 아이의 생물학적 성은 분명 남자(배열)입니다. 하지만 어떤
이유에서인지 늘 여자처럼 변장(포인터로 변환)을 하고 다녔으며, 다만
엄한 부모님(sizeof 연산자) 앞에서는 본래의 타고난 성(배열)을 드러낸
것입니다.

님이 ip 의 type 이 포인터라 주장하시고 sizeof 연산자가 그러한 type 을
올바르게 보여주지 못한다 주장하시는 것은, 위의 예에서 그 아이가 진짜
여자 아이라 오해하고 있는 마을 사람의 생각과 다르지 않은 것입니다.

제가 말씀드린 표준의 개념을 사용하면 sizeof 연산자의 행동도 너무도
자연스럽고 일관되게 설명이 되는데, 님의 잘못된 개념을 사용하면 sizeof
연산자 (혹은 주소 연산자 &) 에서 불연속이 발생할 수 밖에 없는
것입니다. 어느 것이 보다 "자연스러운" 관점인지는 분명합니다.

혹은 설명 방식을 바꾸면 표준의 해석을 이렇게 생각해 볼 수도 있습니다.
일단 표준이 일반적인 사실로 "ip 는 배열이다" 라고 명시적으로
기술한다고 생각해보겠습니다 (실제로는 type system 을 설명하면서 그렇게
기술하고 있습니다). 그런 후 수식 ip 가 나올 수 있는 각 연산자, 각
문장에서 매번 포인터로 변환된다고 기술해 보겠습니다. 즉,

- 대입 연산자의 좌측 피연산자로 배열형이 오면 평가시 포인터로 변환된다
- 대입 연산자의 우측 피연산자로 배열형이 오면 평가시 포인터로 변환된다
- 덧셈 연산자의 양쪽 피연산자로 배열형이 오면 평가시 포인터로 변환된다
- 뺄셈 연산자의 양쪽 피연산자로 배열형이 오면 평가시 포인터로 변환된다
...
- if, while, for 문의 조건 수식에서 배열형은 평가시 포인터로 변환된다
...

와 같은 규정이 따로 있다고 생각해보겠습니다. 이렇게 적어놓고 보니
sizeof 연산자, 주소 연산자, 문자 배열을 초기화하는 경우를 제외하면
모두 위에 적은 것 같은 규정을 포함하게 되는 것입니다. 그러니 보다
경제적인 기술 방법으로

- 수식 내에서 배열은 평가시 포인터로 변환된다

라는 일반적인 규정을 두고, sizeof 연산자를 포함한 3가지 예외 사항을
따로 두게 된 것입니다. 이것이 표준이 배열이 포인터로 "decay" 되는
과정을 기술하는 방법입니다.

하지만, 님의 주장대로 ip 의 type 을 포인터로 본다면, sizeof 연산자나
주소 연산자가 ip 에 적용된 결과를 설명할 방법이 사라지게 됩니다. C
언어에서 배열이 일단 포인터로 변환되면 다시는 배열로 돌아올 수
없습니다! 그럼에도 님 말씀대로 ip 의 type 이 포인터라면 sizeof 연산자
가 적용된 결과에서 ip 는 어쨋든 크기 정보를 포함하는 배열로 돌아와야만
되는 상황이 발생합니다.

ip 는 배열입니다. 수식 평가시에 일정 문맥에서 포인터로 변환되는
것이며, 그와 같은 변환이 일어나지 않는 문맥으로 3가지가 존재하는 것
뿐입니다.

이것이 배열/포인터의 관계를 가장 경제적으로 또한 논리적으로 이해하는
방법입니다.

제가 드릴 수 있는 설명은 다 드린 것 같습니다. 그럼에도 이해가 되지
않으신다면 설명하는 제 능력이 부족한 탓이니, 다른 책이나 자료 등을
통해 결국 같은 개념을 이해하게 되시리라 믿습니다.

새로운 얘깃거리가 있지 않는 이상 이 쓰래드는 이 정도로 마무리되었으면
합니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

wish의 이미지

>줄곧 감정 문제를 피해왔음에도 집요하게 언급하시는 것을
>보니 제게 화가 많이 나신 것 같습니다.

님께서 사용하시는 어휘가 과연 대화에 적합한 중립적인 것인가를 질문 드리고 있습니다. 다른 댓글에서도 이번 댓글처럼 쓰셨으면 처음부터 이야기를 꺼내지도 않았을 것입니다. 님께서 인격적으로 덜 성숙한 것을 스스로 인정했다는 것과는 전혀 별개의 문제입니다. 그리고 제가 님의 감정을 좋지 않게 하거나 화나게 한 것과도 별개의 문제이구요.

[...]
>ip; 라는 수식이 평가 후 갖는 type 이 포인터라는 사실에는 이의가
>없습니다.
[...]
>ip 는 배열입니다.

첫 문장을 ip; 라는 statement 에서 ip 라는 expression이 갖는 형이 평가 후에 포인터라는 뜻으로 받아 들이겠습니다. 뒷 문장이 ip 라는 expression이 평가 전에 배열이다라는 뜻으로 받아 들이겠습니다. ip라는 표현이 지칭하는 것 혹은 ip 라는 변수의 형이 배열이라는 것은 명백합니다. 제 의도는 "ip" 라는 독립적인 expression 의 최종형은 포인터라는 것이고, sizeof(ip)가 "ip"라는 독립적인 expression 의 최종형을 보여주지 않는다는 뜻이었습니다.

>수식 평가시에 일정 문맥에서 포인터로 변환되는
>것이며, 그와 같은 변환이 일어나지 않는 문맥으로 3가지가 존재하는 것
>뿐입니다.

전웅님께서 무슨 말씀을 하시는 지는 잘 알겠습니다. ip 라는 독립적인 표현은 세가지 예외에 들어가지 않으므로, ip 라는 독립적인 표현은 포인터 형으로 변합니다. sizeof(ip) 에서 ip 는 예외 조건에 걸리므로 배열 형 그대로 있습니다. 제 의도는 ip 라는 표현 자체가 수식 평가 이후의 형이 포인터이고, sizeof(ip) 는 그 수식 평가 이후의 최종적인 형을 가르쳐 주지 못한다는 뜻입니다.

다음 예를 통해서 제 의도가 명확히 전달 되기를 바라면서 이만 글 마치겠습니다.

int ip[10]
ip;

라는 코드에서, ip 는 최종적으로 무슨 형인가요? 라는 질문에는 포인터가 답이고, ip 라는 변수는 무슨 형인가요? 라는 질문에는 배열이 답이라는 것이 제 의도입니다. ip 는 배열이지만 수식 평가 이후에는 포인터 형이다라는 것과 다를 바 없는 이야기라고 봅니다.

익명사용자의 이미지

wish님은 정확하게 글읽는 능력을 키울 필요가 있습니다. 이번 스레드만 아니라 다른 글에서도 wish님이 다른 분들이 쓴 글을 제대로 이해하지 못하는 경우를 종종 봐왔습니다. wish님 미워하거나 얕잡아봐서 비난같은 걸 하는게 절대 아닙니다. 상대방의 글을 이해하지 못하면 대화란게 불가능해지기 때문에 지적드리는 겁니다. 의견차이가 아니라 의견소통이 되지 않아 일어나는 싸움은 정말 무의미합니다. 사실 이 문제는 wish님 뿐만 아니라 이곳 KLDP를 포함한 사회 곳곳에서 일어나는 소통단절 현상의 원인이기도 합니다. 상대방의 얘기를 왜곡하지 않고 있는 그대로 듣는 것도 사실은 힘든 기술이며 많은 노력을 필요로 합니다.
지적에 기분 상하실 줄은 압니다만 요즘 들어 소통단절의 현장을 많이 보게 되니 답답해서 적어봤습니다. 미리 용서를 구합니다.

wish의 이미지

충고는 감사합니다.

그러나 제가 어던 부분을 정확하게 잘못 파악하고 있는 지를 지적해 주시지 않는 이상은 제가 잘못 이해하고 있는 지를 알기 힘듭니다. 그리고 제가 고집이 세고, 독단적인 면이 있는 것은 사실입니다만, 그렇다고 반박에 대해서 감정적으로 대응하지는 않는다고 생각합니다. 언제나 반박에 대해서는 제가 가지고 있는 능력 껏 다시 반박하고, 도저히 제 스스로도 틀린 경우가 있을 때 잘못되었다고 인정합니다. 대표적으로 cgi 에 관해서 아마 소타님이었던가와의 논쟁에서 잘못된 주장을 하다가 RFC 읽고 바로 인정했던 적이 있습니다. 이런 자세가 상대방을 짜증나게 하고, 다른 사람들이 저랑 대화를 꺼리게 만드는 요소가 될 지언정, 의사소통의 단절이라고는 생각지 않습니다.

만약 익명사용자님께서 어떤 부분이 정확하게 잘못 이해하고 있다고 지적해 주셨으면 최선을 다해 반박하거나 수긍했을 것입니다.

익명사용자의 이미지

이미 전웅님이 자신의 글을 이해시키기 위해서 옆에서 보기에 애처로울 정도로 수차례나 반복하고, 있는 보따리 다 풀어서 차근차근 설명해가며 지적해드렸습니다. 저는 그 이상 더 잘 지적해낼 능력이 없습니다. wish님은 글을 제대로 읽지 못하고 있는 것도 문제지만 외부에서 받아들인 지식을 자기 안에서 검증하고 확인해서 자신의 것으로 만들지 못하고 있는 문제도 있습니다. 게다가 그런 날것 상태의 남의 지식을 자신의 의견처럼 주장하는 것이 더 큰 문제입니다. wish님은 지금 자신이 무엇을 알고 있느냐보다 자신이 무엇을 모르고 있느냐를 깨닫는게 더 중요합니다. 그래야 올바른 지식이 들어갈 빈자리가 생기고, 논리가 빈약한 주장 대신 논리의 빈자리를 채워줄 질문을 할 수 있습니다. (전웅님이 wish님보고 차라리 질문을 하라고 할때 잠시 실소가 나오기도 했습니다.)
지금 일어나고 있는 의사소통의 문제는 감정적인 것으로 인해 일어나는 것이 아니라 위에서 말씀드린 wish님의 몇가지 문제점 때문에 전웅님의 의견이 전달이 되지 않아서 생기는 의사소통의 장애(단절이라는 말보다는 이 표현이 나은듯 하군요)입니다.
지금 제가 쓴 글도 제대로 이해되리라 기대하진 않습니다. 그래도 눈으로 읽어보긴 하셨을 테니 언젠가 깨달음의 기회가 올때 wish님의 기억 한편에서 도움이 되길 바랍니다.

wish의 이미지

> 위에서 말씀드린 wish님의 몇가지 문제점 때문에 전웅님의 의견이 전달이 되지 않아서 생기는 의사소통의 장애(단절이라는 말
>보다는 이 표현이 나은듯 하군요)입니다.

위에서 말씀드린 제 문제점을 보면,

1) 글을 제대로 읽지 못한다
2) 외부에서 받아들인 지식을 자기 안에서 검증하고 확인해서 자신의 것으로 만들지 못한다
3) 날 것 상태의 남의 지식을 자신의 의견처럼 주장한다.

3가지 입니다.

익명사용자님께서 저런 주장을 하실 수 있는 것은, 1) 2) 3) 의 특징을 제 글에서 발견하셨기 때문입니다. 그렇다면 어느 한 가지라도 저에게 제시를 해 주셔야 제가 님 주장이 사실인 지 아닌 지를 판단할 수 있습니다. 오히려 님께서 쓰시는 글의 방식이 소통의 장애를 가져 오는 것 같습니다. 어떠한 방식으로도 반박이 불가능하고 그렇다고 주장이 사실이라고 생각하는 근거를 제시하지 않으셨기 때문입니다.

오히려 제 의도를 전웅님께서 파악을 못하시고 계셔서 스스로의 글쓰기에 대해서 극단적으로 비관하고 있으니 너무 심려치 마시기 바랍니다.

wish의 이미지

아랫 답글을 수정 하는 글을 쓰고 있는데 익명사용자님께서 댓글을 다시는 바람에 수정이 불가해서 다시 답니다.

"이것 보십시오"
"과격한 표현이라고 생각 지 마시기 바랍니다."
"요즘 세상 참 이상합니다."

이런 식의 표현이 모르는 사람과의 대화에서 사용될 수 있는 중립적인 표현이라고 스스로 생각하시는 지 모르겠습니다. 제 감정이나 님 감정이 상하는 것과는 별개의 문제입니다. 저는 언제나 모르는 사람과의 대화에서는 중립적인 표현을 쓰려고 노력합니다. 그게 최소한의 예의이구요. 전웅님처럼 저에게 감정적인 표현을 직접 썼더라도 그 예의는 지켜져야 합니다. 만약 제가 님 글을 의도적으로 곡해해서 상대방에게 전달하려는 의도를 가지거나 일부러 전웅님의 속을 긁기 위해 썼다고 하더라도,(또 오해를 하실까봐 덧붙입니다만 만약에 입니다.) 그것을 근거로 저에게 직설적인 언사를 하실 권리는 없으십니다. 아니 제가 님께 직접적인 비난을 했다고 하더라도 직접적인 언사를 하실 권리는 없으시죠.

그런데 제가 댓글 하나를 잘못 달았다고 해서, 스스로 생각하기에도 직접적인 언사를 하시고서는, "본의가 아니었지만 사과한다. 그러나 다음번에도 똑같은 언사를 안할 자신이 없다" 라는 말씀을 하실 수 있으시다는 게 놀라울 뿐입니다. 전웅님께서 제 댓글이 전웅님의 감정을 건드렸기 때문에 직접적인 언사를 하셨다고 했는데, 그랬다면 그런 부분을 중립적으로 언급해 주셨어야 합니다. 그렇다면 제가 그 부분에 대해서는 사과를 드렸을 겁니다. 그러나 그렇다고 해도 전웅님께서 직접적인 언사를 하신 것은 정당화가 되지 않습니다. 이건 "감정적이고 직접적인 언사"에 대하인 이야기이지 "감정에 대한" 이야기가 아닙니다.

고등학교 다닐 때 반에서 짜증나게 생겼다고 그 사람 면전에 욕을 해대던 애가 있었습니다. 그것이 옳다고 생각지 않으시다면 글이 맘에 안드신다 해서 직접적인 언사를 해도 된다고 생각하시는게 얼마나 예의에 어긋나는 행동인지를 알아 주셨으면 합니다.

wish의 이미지

제가 제일 앞부분에 대한 것을 빼먹었네요.

>결론적으로 님께서는,
>
>중간과정을 "대충" 때려 맞추니 말이 되는 것 "같기도" 하다. "대충"
>이라고 표현했으니 중간 과정을 따지지 말고, "같기도"라고 표현했으니
>항상 맞는지는 모르겠다.

맞습니다. 이제야 제 의도가 전해 진 것 같군요.

>라고 말씀하시고 싶으신 것이군요! 제가 느끼기에 이는 마치 오리너구리
>를 보고는,
>
>부리 모양만 "대충" 보니 오리임에 맞는 것 "같기도" 하다. 부리만 보고
>말한거니 몸모양 보고 오리가 아니라고 따지지 말고 추측일 뿐이니 항상
>참이라고 주장하는 것도 아니다.

예 그렇습니다. 적절한 비유시군요 :)

>이렇게 해놓으시면 제가 더 이상 무슨 기술적인 말씀을 드릴 수
>있겠습니까? :-(

... 제가 제일 처음 단 댓글이 "기술적이거나" "논리적인" 문제가 아니라고 제가 재차 강조했습니다만 ㅜㅜ 비기술적인 것을 기술적으로 바꾸어놓고 논의를 시작한 것에 대해서 제가 이의를 제기한 겁니다. ;;

>이제 오히려 절 더 화나게 만드시는군요. 카이리님 말씀
>대로 님의 말도 되지 않는 추측으로 인해 나름대로 공들여 작성한 제 글의
>의도가 희석되었다는 사실만 재확인하게 됩니다. 가능한 감정적인 문제는
>배제하기 위해 빨리 덮어버리려 했지만, 이제 제가 처음 감정적인 문체의
>글을 작성했다는 것을 제 스스로 어느 정도 정당화할 수 있을 것
>"같습니다." - 역시나 "같은" 것뿐이니 정당화되었다고 주장하는 것은
>아닙니다. ;-)

맞습니다. 사실 이 문제는 중요하지 않습니다. 설령 제가 님의 말씀을 희석했다고 하더라도, 그것이 제가 님한테 "직접적인 언사"를 들어야 될 이유가 되지 않습니다.

>사적인 이야기라면 모를까 기술적인 이야기를 나누며 "대충", "같기도"를
>연발하는 분과 저는 체질적으로 맞지 않습니다. 이것만은 분명한 사실
>입니다.

기술적인 이야기에 관해서 '대충', '같기도'를 연발하는 사람은 저하고도 전혀 맞지 않는 사람입니다. 문제는 논의의 어느부분이 "기술적" 혹은 "논리적"인가 하는 문제입니다만... 처음 글이 기술적으로 쓴 글도 아니거니와, 제가 누차 기술적이지 않다고 2번 이상 말했던 것 같은데, 왜 기술적인 이야기라고 하시는 지 잘 모르겠습니다. 저의 정확한 의도가 바로 "기술적인 이야기가 아닌 단순한 추측에 대해서, 왜 기술적이지 않느냐면서 스스로 직설적인 언사"를 하셨는지가 제 의문점입니다. 설령 기술적인 이야기에 대해서 기술적이지 않은 것으로 댓글을 달았다고 하더라도, 님께서 감정적인 언사를 할 수 있는 지도 생각해 볼 문제이구요.

전웅님께서 첫 댓글에서 int *f(void) 선언에서 *f 의 리턴형의 경우는 안 맞는다. 라고 하셨으면, "그렇군요 저 방식으로 해도 안 맞는 경우가 있군요. 괜히 잘 맞지도 않는 것을 맞는 것 같다고 해서 죄송합니다." 하고 말았을 겁니다. 그런데 님께서 처음 댓글을 다실 때 스스로 공격적인 표현을 사용했다고 생각 지는 않으신가요? 제가 글 끝에 "과격한 표현이라고 생각지 마시기 바랍니다" 라고 하셨으면, 그것이 올바른 언사라고 생각 하실 건가요? 아니면 제 표현에 공격적인 표현이 있었던가요? 설령 제가 의도적으로 전웅님 글이 맘에 안들어서, 말도 안되는 이야기로 이야기 맥락을 흐려 놓았다고 해도 전웅님 첫 댓글의 표현이 올바르다고 생각지는 않습니다. 하다 못해 설령 게시판에서 상대편이 대 놓고 저에게 쌍욕을 하더라도, 제가 그 사람에게 쌍욕을 할 권리는 없습니다. 부탁입니다만 "과격한 표현이라고 생각지 마시기 바랍니다" 라는 표현이 얼마나 좋지 않은 표현인지 살펴 주셨으면 합니다. 댓글 중에서도 그 부분에 대한 코멘트는 빼놓으셨더군요.

익명사용자의 이미지

별 생각없이 가볍게 쓴 글이 정통으로 반박당하니 꽤나 감정이 상하셨나 보네요.
그 기분은 이해하는데요, 나중에 마음을 가라앉히고 차근차근 읽어보세요.
(감정적인 부분은 빼고 기술적인 부분만.)
님은 C에 대해 잘못 알고 있는 부분이 상당히 많습니다.
이건 감정 상할 일도 아니고 잘못 알고 있던 내용을 고치는 계기가 되니 오히려 행운이라 하겠습니다.
저같으면 전웅님께 감사하다고 인사를 드리겠어요.

익명사용자의 이미지

연산자 우선순위를 생각하면
int *parr[10];은 (int *)parr[10];이랄 수 있기 때문에
*parr만 따로 짤라낼 수 없는 겁니다.

SoftOn의 이미지

int *a; // 1번
int* a; // 2번

저 같은 경우 1번 같은 형태를 씁니다.
저렇게 쓰는 가장 큰 이유는 다음과 같이 쓰면 헷갈립니다.

int* a, b; // 실제로 b는 int 형인데 그냥 언뜻보면 int* 로 정의한듯하고.. ㅎㅎ

cppig1995의 이미지

전 이렇게 씁니다.
int b, *a;



절망으로 코딩하고 희망으로 디버깅하자.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

예진아씨의 이미지

int *a;
int b;

임예진 팬클럽 ♡예진아씨♡ http://cafe.daum.net/imyejin

임예진 팬클럽 ♡예진아씨♡ http://cafe.daum.net/imyejin

전웅의 이미지

> 그냥 이렇게 쓰는게 좋지 않을까요?
>
> int *a;
> int b;
>

imyejin 님의 파워인가요? ^^ 올바를 수 있는 내용을 적었음에도 불구하고
마이너스가 추가되는 이유를 모르겠군요.

변수 선언 방식은 어디까지나 스타일의 문제입니다. 따라서 누가 어떻게
사용하든 어떤 규정된 스타일 원칙을 어기지 않았다면 잘잘못을 단정지을
수 없습니다.

위와 같은 경우 보통 추천되는 방법은 a 와 b 가 서로 관련되어 있는 경우
한 줄에 선언해 주는 것입니다. 즉, 포인터 a 가 항상 b 를 가리키도록
설정되어야 한다면, 둘을 하나의 type specifier 로 선언함으로써 추후
소스 수정을 조금이나마 용이하게 할 수 있다는 것입니다 - b 의 type 을
변경할 경우 a 의 type 역시 자연스럽게 같이 변경되게 됩니다.

하지만, 서로 무관한 변수라면 일반적으로 imyejin 님께서 보여주신
것처럼 서로 분리된 라인에 적는 것이 추천되는 방법입니다 - 이와 같은
내용이 K&R 에도 한 문장으로 나와 있는데 이유가 설명되지 않아 적지
않은 초보분들이 제대로 이해하지 못하고 넘어가는 부분 중 하나입니다.

int m, k;

이 경우 m, k 가 서로 무관한 변수라면 추후 m 이나 k 중 하나의 type
만을 변경하려 할 때 (예를 들면, k 를 double 형으로 변경하려 할 때)
어차피 독립된 선언으로 뽑아 내야 하기 때문에 처음부터 무관한 변수는
독립된 선언으로 처리하는 것이 좋지 않겠느냐는 것이 그와 같은 스타일을
주장하는 이유입니다.

반면,

int *a, b;
int* a, b;

의 문제라면, 컴파일러 입장에서야 어떻게 적든 무관하지만, (SoftOn 님의
말씀대로) 사림의 이해를 위해서는 전자를 추천합니다. pointer
declarator 를 구성하는 * 의 경우 문법적으로 int 가 속해있는
declaration specifier 가 아니라 명칭인 a 에 붙는 것으로 보아야 하기
때문에 이를 선언에서도 표현해 주는 것이 이해에 유리합니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

extrealm의 이미지

저는 int* a 스타일을 좋아합니다.
그리고, 정수형과 정수형 포인터는 같은행에 쓰지 않습니다. (정수형 포인터는 정수형이란 의미보다 포인터란 의미가 더 강하므로 엄연히 다른자료형입니다.)

int* b, c;   // 전 이건 안씁니다

int a;
int *b,*c;

좀 하다보면 아래처럼 고쳐쓰죠.
typedef int INT,*PINT;
INT  a;
PINT b,c;

C 공부 수준에서는 그냥 오버헤드일겝니다만 어차피 프로젝트가 커지면 표준형을 재정의해서 쓰는것이 다반사이니까요.
--
/E/X/T//R/E/A/L/M/ - 그대 품 안의 또하나의 세상

/E/X/T//R/E/A/L/M/ - 그대 품 안의 또하나의 세상

익명사용자의 이미지

나는 왜 이렇게 계속 할까 ㅠ.ㅜ

int* a;
int b;

a는 integer pointer, b는 integer

아니었나... ㅠ.ㅜ

hongminhee의 이미지

int* a;
int b;

저는 C++를 주로 접해서인지, 포인터나 레퍼런스를 일종의 클래스 템플릿이라 여기고 사용합니다.

로미의 이미지

지나가다가 좋은글 읽고 가려니 갑자기 생각이 나서 관련성이 낮을수 있는 댓글을 쓰고 갈렵니다. :p

혹시 이런 책이 필요할때가 되지 않았을까요?

한빛미디어의 좋은코딩 나쁜코딩 정도의 두께로 된 C 와 C++의 이해 혹은 C 와 C++의 차이같은 책이 말이죠...

일단 자기 혼자 보는 소스가 아니라면 기본 규칙정도는 알고 있어야 될텐데
그런 지식만 골라서 만든책을 시중에서 본 적이 없는듯 한데요.

C와 C++은 유사하면서 유사하지 않은 二卵性雙生兒 같은 느낌(?)인데 어디 메뉴얼이라도 구하고 싶은 심정이네요.

혹시 메뉴얼이나 그런책에 관련된 정보를 가지고 계신분은 알려주세요.

예를들어 변수선언, 함수같은 변수이름짓기 규칙, 데이터 타입, 함수타입 선언위치 같은것 말이죠...

꼬리말 : 몇일전 일 입니다. 저의 동생은 분명히 VS에서 API와 MFC를 이용해서 코딩하고 있었습니다. 근데 코딩스탈을 보니 마치 C를 코딩하는듯한...

Signature:
끝까지 읽어 주셔서 감사합니다.(이봐 로미, 뭐가 감사한거야?!)

혹시 댓글로 싸움을 즐기려는 님!?
당신은 眞性 변퉤 입니다~ :P

Signature:
끝까지 읽어 주셔서 감사합니다.(이봐 로미, 뭐가 감사한거야?!)

혹시 댓글로 싸움을 즐기려는 님!?
당신은 眞性 변퉤 입니다~ :P

이제는 무늬만 백수로 가장한 개발자가 아닌 진정한 개발자가 되어야겠다.
이제는 학생으로 가장한 백수가 아닌 진짜 백수가 되어야겠다.

언제나 newbie의 마음가짐.

전웅의 이미지

일주일 정도 개인적인 사정으로 인터넷 연결이 되지 않는 곳에 머물게 되어
다소 뒤늦게 답글 남깁니다 - 덕분에 여독이 풀리기도 전에 csc 와 질답
게시판에 글 남기느라 반나절을 보내게 되네요. 중독인가 봅니다. :-)

지루하게 반복된 감이 없진 않지만 기술적인 문제는 이제 마무리가 된 듯
합니다 - 어느 익명 사용자 분께서도 언급하셨듯이 저로서는 제가 꺼내놓을
수 있는 설명 방법은 모두 동원했다고 생각하며, 이제 제 의도가 올바르게
전달되느냐는 읽는 분들의 몫이라 생각합니다.

"배열 vs. 포인터" 라는 지극히 고전적인 (따라서 이미 많은 답이 나와
있는) 문제로 기술적인 내용이 마무리되어 아쉬운 감이 없진 않지만, 썩
나쁘지 않은 이야기 주제에 감정적 문제 (혹은 누군가의 표현처럼 감정
중립적 표현의 사용 문제) 가 결부되어 전체적인 글의 흐름이 지저분하게
되어 버린 듯 합니다. 일차적인 책임은 저에게 있다는 생각이 들어 가능한
기술적 내용으로 흐름의 무게를 옮기고 그 외의 문제는 개인적인 의사소통
을 통해 해결하려 했으나, 직접적인 제 답변이 없음에도 wish 님께서 3-4번
정도를 반복해 비슷한 취지의 글을 올리고 계셔서 이곳에 글 남깁니다.

최초 감정적인 표현을 담은 첫 글은 님의 무책임한 "대충" 설명으로 제
글의 (이른바 제가 생각하는) "fine point" 가 희석되었다는 사실이 절
불편하게 만들어 남기게 되었습니다. 물론, 동일한 내용의 글이 제 글에
대한 직접적 답변이 아닌 형태로 남겨졌다면 보다 이성적인 반응으로 답을
하지 않았을까 생각해 봅니다.

하지만, 지리한 논의가 이어지면서 님이 기술적 내용에 대해 토론을 진행
하는 태도가 저를 꾸준히 불편하게 만들기에 충분했습니다. 감정적 문제는
지극히 개인적인 관점이라 다른 분들로서는 그 이유의 타당성을 이해하기
힘들 수도 있겠지만 최소한 저로서는 다음과 같은 사실들로 인해 저로
하여금 "도대체 무얼 위해서 내 아까운 시간 들어가며 답변을 남겨야
하나?" 라는 무책임한 생각까지 들도록 만들었습니다.

1. 토론 도중 몇몇 사용자분들께서 님께 도움되는 조언의 말씀을
남기셨습니다 - 제게 감사해야 한다는 등의 이야기를 의미하는 것이
아니라, 님이 기술적 토론을 진행하면서 취하면 더 보탬이 될 부분에 대한
이야기를 의미하는 것입니다. 하지만, 정작 지극히 엄격한 논리적 태도를
취해야 하는 첫 글에서는 그러지 않으셨던 분이 다른 분들이 예의를
갖춰가며 남기신 조언의 글마다 갑자기 논리적으로 근거를 요구하시고
계시더군요. 다른 사람의 조언을 취하고 취하지 않고는 님의 판단입니다만,
감정적 표현을 사용하는 제 인격을 님이 의심하듯이 저 역시 그와 같은
일련의 과정을 통해 님의 인격을 의심하지 않을 수 없었습니다.

2. 사람은 누구나 실수를 할 수 있습니다. 저 역시 적지 않은 시간 C
언어를 보아왔지만 (최근? 글에서 볼 수 있듯이) 아직도 실수를 하고 또
그런 실수를 통해 다시 배우고 있습니다. 실수를 최소화하기 위해 노력해야
하는 것은 당연한 이야기지만, 실수를 했다는 사실만으로 문제가 되는 것은
아닙니다. 그 점에서 제가 님의 첫 글에 대해 감정적으로 대처한 부분에는
문제가 있음이 확실합니다. 하지만, 그 이후 님께서 말장난에 가까운
반응으로 님의 잘못을 논리적으로 합리화하시려 했던 모습에는 여전히
불편함을 느끼지 않을 수 없습니다. 의도적으로 그려셨는지는 아직도
확신이 서지 않으나, 참/거짓이 분명한 문제에 대해 참/거짓이 불분명한
태도를 취한 후 이에 대한 제 지적이 따르자 원래부터 참/거짓을 분명히
하자고 적은 글은 아니라는 식의 반응을 보이니 제 개인적인 관점으로는
편안히 받아들이기가 어려웠습니다. 오히려 애초부터 참/거짓을 분명히
하는 제 글에 의도적으로 그 경계를 흐리는 답글을 남기셨다는 사실을
재확인하는 계기가 되었을 뿐이었습니다.

3. 정확히 모르고 계신 부분에 대해 질문의 형태를 취하기 보다는 불충분한
근거를 제시하며 상당히 단정적으로 적고 계신 부분도 저로선 개인적으로
불편함을 느끼는 부분입니다. 농담으로 "악플보다 무플이 더 무섭다"는
이야기도 있습니다만, 기술적 내용에 있어서는 "잘못된 답변이 무플보다 더
무섭다"는 것이 제 생각입니다. 잘못된 내용에 제법 권위있는 책의
내용까지 올바른 이해 없이 아전인수 격으로 인용하시니 한참 스폰지처럼
지식을 빨아들이는 분들에게는 잘못된 내용이 전달되기 쉬운 상황이
됩니다. 물론, 모르고 계시는 부분이 있을 수 있으니 그와 같은 잘못된
답변이 나올 수 있다는 것은 지극히 당연한 사실입니다. 하지만, 님께서
잘못 알고 계신 부분이 무엇인지 알려드리고 이를 고쳐가는 과정이 다른
경우보다 결코 쉽지 않았다는 부분 만큼은 사실입니다 - 직설적으로 표현해
"알려주고도 기분 나쁜" 경우가 되었습니다. 제 글에 잘못된 내용의 답이
달리고 그 답으로 인해 글타래를 읽는 다른 분들의 오해가 있을까 하는
우려 때문에 계속 설명을 하게 되었지만, 그 과정에서 님의 이해할 수 없는
고집으로 인해 상당히 지칠 수 밖에 없었습니다.

4. 토론이 진행되면서, 일부 부분에 대해 분명 잘못 알고 계시던 사실에
지적이 더해지니 마치 원래는 제대로 알고 있었으나 표현을 제대로 하지
못해 오해가 생긴 것처럼 말을 바꾸시는 부분도 상당히 불쾌함을 느끼게
합니다. 물론, 제가 이런 말씀을 드리고 근거까지 매달아 놓으면 또 이런
저런 반박을 하시겠지만 (그래서 하지 않습니다), (최소한 익명 사용자 한
분을 포함해) 제 느낌은 분명 그렇습니다. 혹은 제 느낌이 사실과
다르다면, 님께서 올바르게 이해하고 계신 사실이 저에게 전달되기까지의
과정이 쉽지 않다는 사실이 안타까울 뿐입니다.

한때 무분별한 사용자들(?)로 게시판이 시끄러운 시점에 맞춰 이 글이
진행되어 본의 아니게 지저분한 제 글을 읽게 된 분들에게는 죄송한
마음입니다.

하지만 가능한 침착하게 처음부터 지금까지의 글을 여러번 반복해 읽어도
(wish 님이 저를 이해할 수 없듯이) wish 님이 취해오신 태도가 제게
불쾌함을 느끼게 만든다는 사실에는 변화가 없습니다.

하고 싶은 이야기는 많지만 이만 줄이도록 하겠습니다. 앞으로도 wish 님의
사실이 아닌 답변을 우연히라도 보게 된다면, 제가 알고 있는 바를
설명드리기 위해 노력하겠지만, 그 과정에서 이번 논의와 비슷한 태도를
다시 확인하게 된다면 더 이상의 반응은 보이지 않으려 합니다. 아무리
생각해도 wish 님에게나 저에게나 더 많은 시간을 할애해야 하는 소중한
일들이 있다고 생각합니다 - 저 역시 이기적인 보통 (혹은 그보다 못된)
사람인지라 제가 얻을 바 없는 일에 지나친 투자를 하고 싶은 생각은
없습니다.

그럼...

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

죠커의 이미지

C FAQ에도 나온 고전적인 내용을 전웅씨가 힘들게 계속 말하게 된 것은 누구에도 유익하지 못한 상황 같습니다. 뭔가 많이 아쉬운 쓰레드이군요.

익명 사용자의 이미지

맙소사~
포인터는 포인터이고 인티저는 인티저일뿐

사랑천사의 이미지

"C언어 펀더멘털"을 샀는데.. 어떻게 읽어야 할 지 고민됩니다. 독서 확대경을 구해야 할 지(전자식으로...) 아니면 스캔을 써서 아르미로 텍스트 인식을 시켜야 할지.. 텍스트 인식을 시키면 정확도가 너무 떨어져서 보다가 공부가 안 될 ㄷ읏.. 전웅님께서 많이 나타나시기에 생각이 나서 적어 봅니다. 못 보는 동안 글이 많이 달렸군요. 근대 이 글이 아직도 여기 있다는 것이 신기합니다 음.
----
Lee Yeosong(이여송 사도요한)
E-Mail: yeosong@gmail.com
MSN: ysnglee2000@hotmail.com
----
웃음... 행복... 평화... (진정한...) 희망... 사랑... 이 세상 모든것이 그렇다면 얼마나 좋을까...(꿈 속의 바램일 뿐인가...)

사람천사