포인터를 어떻게 이해하셨나요?

geekforum의 이미지

C언어를 공부하고 있는데 포인터 때문에 번번히 막히는군요. 책을 볼때는 알것 같은데 막상 이걸 어떻게 써야 할지, 왜 포인터라는게 있는 것인지 막연하네요. 예제는 그냥그냥 풀수 있고 뭔가 알것 같기는 한데 확실히 손에 잡히지는 않는 그런 상태입니다. 그냥 포인터 변수만 나오면 괜찮은데 함수 포인터다, 구조체 포인터다...갈수록 복잡해지더군요.

여러분들은 포인터를 어떻게 이해하셨는지요? 책을 보면 각자 비슷비슷하게 설명은 하고 있지만 제대로 이해가 되지는 않습니다. 포인터를 어떻게 이해하면 좋을지, 포인터를 언제/어떻게 사용해야 할지 여러분이 가지고 계신 노하우를 좀 전수해 주시면 안될까요?

댓글

익명 사용자의 이미지

포인터문서를 올리고 싶지만 어떻게 올리는 건지 모르겠네요..일단 여기 괄리한테 올려달라고 메일로 문서를 첨부해서 보냈는데..
올려지면 보셈...

익명 사용자의 이미지

좋은 답변이 많이 있네요.
하지만 질문자가 올린 "왜 포인터를 쓰는 지.."가 빠진 것 같네요. (사실 대충 봤는데)
포인터가 있는 이유는 컴퓨터 구조를 알면 이해가 됩니다.
컴퓨터는 메모리 주소를 레지스트리로 불러 들여서 연산을 합니다.
사실 모든 것이 메모리 주소라고 해도 과언이 아닙니다. 레지스트리도 주소가 있으니까요.
저급언어란 컴퓨터가 동작하는 방식을 그대로 구현 할 수 있는 언어입니다.
C언어가 저급언어의 특성을 가지고 있다는게 포인터때문이기도 합니다.

익명 사용자의 이미지

레지스터는 주소가 없답니다.
CPU코어 내부에서는 신호가 물리적으로 움직일뿐 주소따위는 갖지 않는답니다. 명령어에 포함된 좌표값만이 레지스터를 지정할 수 있을 뿐이랍니다.
다시말해서, 메모리와 포트만이 주소를 가집니다. (인텔의 제어용 프로세서인 80196만이 아주 예외적으로 레지스터를 주소 대응시킬 수는 있죠)

INTEL : AX, BX, CX, DX, SI, DI, ....
MC68K : D0..7, A0..7
SPARC : R0..R15 (8개 레지스터 단위로 스와핑 가능)

참고하세요.

익명 사용자의 이미지

잘 이해가 가지 않는데요.
명령어에 포함된 좌표값을 주소로 볼 수 있는게 아닌지요?
그리고 주소라는게 원래 물리적인 신호로 찾는게 아닌가요?
레지스터가 주소가 없다는게 이해가 아직 안되네요.

AX 라는 명령어도 그 레지스터를 정확하게 가르키려면
주소가 있어야 하고 주소라는건 CPU안이든 밖이든 다 같은 전기 신호 아닌가요?

익명 사용자의 이미지

레지스터를 셀렉트하는건 주소가 아니라 명령어입니다.
명령어는 디코드 돼서 레지스터에 셀렉트신호를 보냅니다.
그 과정이 마이크로 시퀀서든, 하드와이어드 컨트롤이든
레지스터 셀렉트 신호는 주소로 구현될 수 있습니다.
그러나 그 주소는 일반적인 주소가 아니고,
모든 레지스터 셀렉트 신호가 주소로 구현되지 않습니다.

말 하다보니 예긴데

레퍼런스는 포인터로 구현될 수 있습니다.
그러나 모든 레퍼런스가 포인터로 구현된 것은 아닙니다.

익명 사용자의 이미지

명령어에 주소가 있다고 볼 수 있지 않나요?
레지스터의 갯수와 instruction set의 레지스터 bit의 숫자가
정확히 들어 맞는다는 점에서(ex: sparc 2^5=35개)
특정 레지스터를 bit로 주소로 해석하여 그 레지스터를 집어줍니다.

익명 사용자의 이미지

실수입니다. 너그러이 이해를 바랍니다.

ARM : R0..R15 (R14, R15는 특수목적)
SPARC : G0..7 I0..7 L0..7 O0..7 (I와 L은 스와핑가능)
MIPS : R0..R31 (몇몇 레지스터는 특수목적)

익명 사용자의 이미지

레지스터입니다.

익명 사용자의 이미지

C가 영어권에서 만들어 졌으므로, 영어로는 명확하지여.
우리말로는 순서가 맞지가 않지만...

아래 분이 쓰신
char (*(*x[10])())(int,int);
라는 선언도 영어로는 명확합니다.
우리말로는 무진장 꼬이지만...

the x is a array[10] of pointer to function()
returning pointer to function(int, int)
returning char.
이 되겠네요. 간단히 하면 10칸 짜리 배열이져.

우리말은 순서가 반대니까, "문자형을 리턴하는
함수(int,int)를 가리키는 포인터를 리턴하는 함수를
가리키는 포인터로 이루어진 10칸짜리 배열"
(==> 도대체 이게 무슨 말이여?)이 되겠네요.

앞서 말씀하신 분들의 의견 주소와 데이타... 다
맞지만, 내용을 담는 그릇이 영어를 기반으로 하고
있기 때문에 영어의 문법을 그대로 따르고 있는 것
같습니다. 영어권 사람에게는 우리에게 만큰 어렵지는
않겠지여..

감사함다.

익명 사용자의 이미지

여기서 말하는 포인터는 포인터 변수를 말하는 거겠죠?
포인터라는 의미는 추상적인 뜻으로 그냥 어떤것을 가리킨다는 것을 말합니다. 그 어떤것은 자료형인 경우가 대부분이겠죠.씨언어에서 제공하는 기초자료형(char,int,long..)
일수도 있고,그런 기초자료형을 조합하여 프로그래머가 정의한 자료형일수도 있습니다.그리고 씨언어에서는 함수에 대한 포인터 자료형도 제공합니다(쉽게 얘기하면 함수에 대한 포인터변수).
그런 어떠한 것을 가리키는 것을 포인터라고 하는데 이포인터라는 개념은 씨언어에서 정의한 개념이고 물리적으로 봤을때에는 대부분 메모리주소를 뜻합니다.이 메모리 주소값 자체를 씨에서는 포인터 상수라고 말하고 그 상수를 저장하는 공간을 포인터 변수라고 얘기하죠0xffffffff 가 의미하는것이 메모리어딘가의 주소라면 포인터 상수가 되며 어떤 변수가 그 값을 유지하고 있다면 그변수는
포인터 변수입니다.
여기서 자료형에 대해서 잠시 얘기를 해보죠.학문적인 정의는 저도 까먹었고,직관적인 개념은 어떤 데이터의 표현 방법과 거기에 관련된
연산을 포함하는 개념입니다.씨언어의 기초자료형중 int 형을 보면
데이터의 표현은 일반적으로 16비트 프로세서의 경우 -2^15 ~ + 2^15-1
까지이고 연산은 +,-,*,/,%,..그외 비트연산 등등을 제공합니다.실제
수학에서 말하는 정수가 아니죠.단지 씨언어 에서 수학에서 정의한 정수
비스무리하게 표현될수 있도록 정의한거죠.
그럼 마찬가지로 포인터자료형(char*,int*,..)의 경우 데이터의 표현은
주소(16비트일경우 2바이트)이고,연산은 *,++,--,+,-,.. 등등의 연산을
제공합니다.포인터연산중의 하나인 * 이것은 포인터변수가 가지고 있는
주소값이 가리키는 주소값을 반환합니다.++연산은 포인터변수의 값(주소)을
증가시키는데 정수 기초자료형연산자 ++ 와 비슷하지만 포인터 형의 단위로
증가시키죠.즉 연산자는 같은 것을 쓰지만 정의된 자료형(int형이냐,int*형이냐)
에 따라 실제 연산이 달라집니다.
이중포인터도 그것의 연산 단위로 보시면 이해가 한결 쉬울것이고 ,실제로 이중포인
터라는 개념도 따로 존재하는거시 아니고 포인터형이 겹칠때 쓰는 말이므로 단일포인터
따로,이중포인터 따로 삼중포인터 따로 이해하실 필요없습니다.
int *p; 라는 표현은 실제 int* p; 라는 표현이 더 적절합니다. 별표를 왼쪽에 붙이느냐
오른쪽에 붙이느냐 실제 결과는 같지만 그 의미상 왼쪽에 붙이는게 이해하는것이 쉽죠.
씨언어에서 변수를 선언할때 왼쪽에는 자료형이 오고(기초자료형이던 사용자가 정의한 자료형이든)
오른쪽에는 그 자료형의 이름이 오죠.
int *p; 보다는 int* p ;//정수형에대한 포인터형(int*) 변수 p 선언
마찬가지로 이중포인터를 이해해보죠.
int **p; --> (int*)* p; 즉 정수형을 가리키는 포인터 자료형에 대한 포인터 변수의 선언입니다.
다른형태로 보면
typedef int* INT_PTR ;
typedef INT_PTR* STUDENT_PTR ;
typedef STUDENT_PTR p ; //int **p; 와 같은 표현

전 이런식으로 typedef 문을 즐겨사용하며 소스를 분석할때나 코딩할때도 이런형태로 작성하는것이
이해도 쉽고 머리가 아프지 않습니다.남의 소스를 볼때 이것이 이중포인터냐,삼중포인터냐를 찾는
다고 헤매는 경우가 많은데 실제로 그런정보가 필요할때도 있지만 대부분의 경우 왼쪽에 오는 자료형
이 어떤것이다라는정보만 알면 충분할때가 많습니다(위의 예에서 변수 p는 STUDENT_PTR형 자료형이라
는 것이 중요하지 이중포인터라는것은 중요하지 않습니다.)
횡설수설한 설명이었지만 ,제가 보기에 포인터에서 많이 헤매신다면 어셈블리를 이해해보시는것도
분명 도움이 되겠지만,개인적으로 좀더 크게 보시고 데이터의 표현방법 과 연산에 중점을 둔 자료구조에
관련된 문서나 책등을 참고해보시는것도 도움이 될듯합니다.

익명 사용자의 이미지

여러분이 써 주셨지만 어셈블리를 배우시면
포인터 이해하는데에는 문제가 없을 겁니다.
어셈블리에서 메모리 주소 연산 없으면
시체이므로 ;_;

그나저나 저는 perl의 hashref나 glob가
더 어렵게 느껴지는군요. :<

%{ ${$a->{b}->{c}->{d}}->{$a[4]} }

뭐 이런거... ;_;

knight2000_의 이미지

음... 저는 그냥 쉽게 생각합니다.

포인터는...
우편번호부에 나오는 우편번호다.

우편번호가 가지는 의미는... 그 우편 번호 위치에... 우편번호가 가리키는 주소가 있죠.

540-742 라는 우편번호는 포인터와 마찬가지로 주소값을 가집니다.
그 주소값에 해당하는 실제 객체는 따로 있죠.
540-742에 해당하는 객체는 순천대학교 이네요... ㅡ.ㅡ;

그것도 아니라면...
전화번호부일수도 있죠.

이 번호들은 서로 더할 수 있나요? 물론 더하는 사람도 있지만, 그건 장난이 되겠죠. C/C++는 이 장난을 금지한다는 뜻에서 포인터끼리 연산하는 것을 막고 있죠.

우편번호를 정렬하면 어느 것이 먼저고 어느 것이 나중인지 알 수 있죠. 이와 같이 포인터의 크기 비교는 가능하죠.
(앗, 이 부분에서... 가물가물... ㅡ.ㅡ; 제발 내가 하는 말이 맞기를...)

아무튼 이렇게 저는 이해하고 있습니다.

iron의 이미지

아주 간단합니다.
우선 포인터가 쉽다. 포인터는 쉬운거다. 라고 생각합니다. 자기 최면이나, 자기 암시에 능하시다면 더 유리합니다.
그 다음에는 한번 프로그램을 짜보고 컴파일해봅니다.
에러가 나면 &,* 등을 덧붙여 가면 찍어봅니다 -.-;;
컴파일에 성공하고 정상 작동하였다면, 우선 한숨 돌리고, 천천히 들여다 봅니다.
이해가 되셨다면, '움 포인터는 다 배웠군' 하면서 넘어가시면 되구, 안되셨더면, 다시 두번째 단계로 돌아가시면 됩니다.
포인터가 어렵다고는 하지만, 쓰다보면 가끔 헷갈리는 것이지, 개념자체가 이해할수 없을 만큼 어렵다거나 한것은 아닙니다. 그런거라면, 후에 배우실 다른 것들이나, 다른 과목들이 더 어렵죠.
그럼.

Bluemetal의 이미지

컴터 메모리를 논리적으로 봤을때
<주소> : <주소가 가진 공간>
요 2개로 구성 되어있죠.

<주소>로 장난치는 것이 포인터라고 하며 <주소가 가진 공간>으로 장난치는게 일반 변수라고 하겠져..

쩝..간단하지 않습니까?
C에서 포인터가 짜증난다면
어셈에서 프로그래밍 해보십시오
아주 명확합니다.

C에서 처럼 캐릭터포인터, 정수 포인터 어쩌고
함수 포인터는 또 저쩌고.. 정말 짜증 나죠.
허나 어셈에서는 그져 주소는 주소
일뿐 어떤 틀이 전혀 없으므로 개념 익히기에는 더욱 쉽지 않을까 합니다.

컴터에서 99%의 틀은 그저 하나의 논리적
구성체일뿐이죠..투명하게 바라보세요 :)

익명 사용자의 이미지

'C는 고급언어와 저급언어사이에 낀 애매모호한(중급?)언어다' 라고
어디선가 본듯하네요.

이런말이 나온배경이 바로 포인터지요.

실제로 C의 모든것은 포인터로 이루어 졌다고 해도 과언은 아닙니다.

가장 친밀한(?) printf에 대해서 간단히 언급하죠.

int printf(const char *fmt, ...);
이렇죠 아마...

보통(잘못된 습관입니다만) 호출시
printf("hello world\n");
이런식이겠죠...

설명을 위해 잠시 형태를 바꿔보겠습니다.
static const char *str = "hello world";
static const char *fmt = "%s\n";
printf(fmt, str);

위와 동일한 결과를 출력합니다.

일단 "hello world", "%s\n"은 모두 .data영역에 symbol로서 등록되어 있습니다.
str에는 "hello world"의 주소값이 들어가 있고, fmt도 마찬가집니다.

asm으로 넘어가 보겠습니다.

..중략..
push str
push fmt
push eip
call printf
..생략..

대략 이런형태로 되겠죠...

str, fmt는 주소값이죠(흔히 말하는 포인터겠죠)
eip는 현재의 instruction pointer의 값을 저장한 register입니다.
call printf로 되어 있지만, strip하고 나면 결과적으로 남는것은
call [func addr]이 됩니다. 역시 포인터죠.

너무 장황했나요...

*** 결론은 바로 모든것은 포틴터로 동작한다는 것입니다.
*** 이말은 곧 포인터를 잘 이해한다면 원활하고도 효율적인 무언가가 된다는 거겠죠.

* 생각나는데로 두서없이 적어서 틀린부분이 있을수도 있습니다.

익명 사용자의 이미지

포인터를 이해하는건 의외로 간단합니다.

예제를 많이 풀어보고 코드를 많이 접해보는수밖에 없죠.. 단순히 포인터가 무엇인지 이해하는게 중요한게 아니고 어떻게 활용하느냐가 더 어려운 문제기 때문입니다. (포인터를 최대한 안쓰고도 멋진 프로그램을 만들수 있긴 합니다)

포인터를 쓸수밖에 없는 경우는.. 보통 함수에 문자열을 전달할때나 함수에서 배열을 다룰때 정도가 아닐까 싶네요.. 배열은 포인터로 전달할수밖에 없으니까요..

속도는 느려도.. 자바가 왕입니다.

익명 사용자의 이미지

아싸~
저랑 비슷하게 사용하시는 거 같네요~
struct역시 포인터로 많이 전달해요.

-영희-

익명 사용자의 이미지

엉뚱한 소리일지는 모르겠는데요..

저같은 경우는 자바를 많이 다루다 보니 C에서의 포인터가 쉬워지더군요..

자바에서의 객체참조가 결국 포인터랑 같은거지요..

C가 정말 강력하단걸 부인할순 없지만..
C는 참 불친절합니다... -.-

익명 사용자의 이미지

매우 off topic하긴 합니다만..(죄송^^;)

C에서 선언문(declaration statement)가 참 절묘하지 않나요?

basic type(char,int...)와 *,함수(),배열[],괄호(..) 이것들로만 이루어져서

나타내고자 하는 것을 다 나타낼 수 있잖아요..

char ((*x[10])())(int,int);

요런 괴상한 것도 가능하구요..-_-;

익명 사용자의 이미지

char ((*x[10])())(int,int);
이 아니라
char (*(*x[10])())(int,int);
로 정정~

ihavnoid의 이미지

Anonymous wrote...
> char ((*x[10])())(int,int);
> 이 아니라
> char (*(*x[10])())(int,int);
> 로 정정~

헷갈려여-_-;;

이것의 정체는....?

typedef char (*func_pointer_returning_char)(int,int);
typedef func_pointer_returning_char (*the_type[10])();
the_type x;

이건가요..?? (틀렸나..??)

즉, x는 char를 return하고 int를 2개 받는 함수를 향한 포인터를 return하고 아무것도 안 받는 함수들의 포인터의 크기 10짜리 array인 것인가요?

헥헥...-_-;; 실전에서는 쓸일이 없겠고... 대부분의 정상적인 경우라면...
typedef와 함께 써서 저런 험악한 문장은 안 나오겠죠? ㅋㅋ
(저런거 그대로 썼다가는 같은 팀원들에게 무쟈게 욕먹을수도-_-;;)

Consider the ravens: for they neither sow nor reap; which neither have storehouse nor barn; and God feedeth them: how much more are ye better than the fowls?
Luke 12:24

익명 사용자의 이미지

거추장스럽게 이해하지 말고,
단지 메모리 주소라고 취급하면 됩니다.

함수 포인터 또한 코드를 저장하고 있는 메모리 주소입니다.

제어문(switch,while,for)들도 단지 if문의 변형으로 보면 특별히 고민할 것도 없습니다.

아주 Low Level로 내려가면, 다시말해 CPU Instruction Set으로 가면, 기본적인 연산, Memory Addressing, Branch가 전부입니다.

얼핏보면 정말 단순 무식해보이는 이 집합에서
Mapping["Hajiwon"] = 1;
이라는 C++ 구문이 존재한다는 것이 얼핏보면 경이롭습니다.
그러나 단지 이 자체의 구문만 이해하자면 특별한 것은 없습니다.

익명 사용자의 이미지

computer architecture 를 공부하십시요~
한방입니다.~

익명 사용자의 이미지

어셈블리를 권장합니다.

간접 주소 지정 이 C 에서 포인터와
거의 동일한 녀석이죠.

익명 사용자의 이미지

한순간에 깨달은 것이 아니고 오랜시간에 걸쳐 어떻게 쓰다보니 이해한 거라 잘은 모르겠지만 아마도 메모리 할당이란 개념을 알게되면서 포인터를 이해하게 된 것 같습니다. 사실 포인터의 의미는 간단하죠. 포인터=지시자. 지금 생각하면 무척이나 간단한 개념인데 배울때는 왜그렇게 어렵고 힘들었는지... 아마도 컴퓨터의 구조에 대한 이해가 부족해서 였을듯 합니다.

익명 사용자의 이미지

동의를 나타내면서 첨언을 하자면요...
우선 포인터 = 주소변수입니다.
그리고, 포인터가 어려운 것은 포인터를 응용한 함수의 응용들이 처음 접하고자 하는 사람들에게 헷갈리게 만든다는 것이죠.
그래서 보고보고 또보고, 쓰고 또 쓰고 하면 저절로 그 포인터 응용을 배워서 그때서야 "아하~~ 포인터가 별개 아니구나"라고 생각하죠.

저의 경험이었습니다.

익명 사용자의 이미지

역시 커니건과 리치 책을 보는 것이 가장 좋을
듯 합니다.

요약해 보면 이렇습니다.

1. 포인터는 객체의 주소를 담고 있는 변수입니다.

2. 포인터 관련 연산자는 *과 &입니다.

3. &는 객체의 주소를 추출해 줍니다.

---여기까지는 상식이고 아래 부터가 중요합니다.

4. * 연산자는 "포인터에만 적용되며" 포인터 변수가
가리키는 객체에 액세스하여 그 컨텐츠를
추출해 줍니다. 즉, deref합니다. (deref는 간접이
아니라 거슬러 올라간다는 의미를 갖습
니다. 즉, 포인터 a에 *를 적용하여 *a로 표현하면
포인터 변수 a가 담고 있는 컨텐츠(주소)를 따라
"거슬러 올라가" 그 주소에 담겨 있는 컨텐츠를
추출하게 됩니다. (C의 관점에서 deref를 간접이라
지칭하면 * 연산자의 의미를 알 수 없습니다)
또, * 연산자는 언제나 rvalue입니다. 즉,
주소가 아니라 컨텐츠를 건네줍니다.

5. 포인터 변수의 선언 예는 다음과 같습니다.
int *ptr;
많은 분들이 착각하고 계시지만, *는 포인터를
선언하는 연산자가 아닙니다. *는 deref 연산자
일 뿐입니다. 위의 선언은 ptr이 포인터이며
ptr을 deref(*)하면 int 타입의 값을 얻을 수 있다는
의미를 갖습니다. 포인터 변수를 선언할 때
"포인터 변수 선언용 연산자를 사용하지 않고"
deref 연산자를 사용한다는 것은 대단히
절묘한 아이디어입니다. 이때문에 C 언어에서는
대단히 축약된 표현이 가능해 집니다.

몇 가지 예를 들면 char * f() 같은 표현은 함수의
값(즉, 리턴값)을 deref하면 char형 값을 얻을 수
(deref) 있다는 뜻입니다.
좀 더 직접적으로 말하면 f()의 값이 포인터이며
(*는 포인터에만 적용되므로), 그 포인터는
char 크기의 메모리 셀을 가리키고 있음을
뜻합니다.

또, char (* f) ()는 f가 포인터이며 char -()라는
함수, 즉 리턴값이 char인 함수를 가리키고 있음을
뜻합니다. (함수 포인터)

또, char (* (* x ())[])()를 보겠습니다.
(* x())에서 함수 x()의 값이 포인터임을 알수
있습니다. 그리고 그 포인터는 (* -[])를
가리키고 있습니다. int * a[]라는 표현을
떠올려 보시면 위 표현은 포인터들을 요소로 갖는
배열임을 알 수 있습니다.
그리고 그 배열의 요소는 char -()를 가리키고
있음을 알 수 있습니다.
즉, x()의 리턴값은 배열을 가리키는 포인터이며,
그 배열은 포인터들을 요소로 하고 있으며,
배열의 요소인 포인터는 함수값이 char 타입인
함수를 가리키는 함수 포인터인 것입니다.

또, char ** str이라는 표현을 보겠습니다.
*이 적용되어 있으니 str은 포인터입니다 : *str
그런데 이 포인터는 포인터를 가리키고 있습니다:
*(*str)
그리고 str이라는 포인터가 가리키는 포인터가
가리키는 것은 char 타입의 메모리 셀입니다.
: char (*(* str))
이것이 이중 포인터입니다.

포인터를 어떻게, 왜 사용해야 하는가 역시
커니건과 리치의 책을 읽어 보는 것이 가장
좋을 거 같습니다. - 저도 요즘 즐겁게 읽고
있답니다.^^ C의 절묘함에 감탄하면서...

요점: int * a[]라는 표현은 배열의 요소가 int*형
임을 뜻하지 않습니다. int* 형은 없습니다.
int * a[]는 배열 a의 요소가 포인터이며 int크기의
메모리 셀을 가리킨다는 뜻입니다.
int*를 하나의 타입으로 간주하는 것은 만악의
원흉이라 사료됩니다. - 엄격한 의미에서 C에서
포인터는 선언되지 않고 단지 사용될 뿐입니다.
(그리고 노파심에서 하는 말이지만 a는 포인터
입니다. 배열 이름은 포인터이기 때문에.)

디버그를 많이 당할 것으로 생각됨...-_-

익명 사용자의 이미지

참고로, 저의 경우 <**str>의 경우는 '현재 str에 주소가 들어있고 str의 주소 자체를 수정하려고 하는구나'로 코드를 읽습니다. 그 외의 경우는 아직 못 본것 같습니다. str의 인수를 넘기는 쪽에서는 아마도 &str의 형태로 넘겼을 겁니다.

**를 이해하는데는 Single Linked List가 가장 효과적이지 않을까 생각합니다.

익명 사용자의 이미지

Anonymous wrote...
> 또, * 연산자는 언제나 rvalue입니다. 즉,
> 주소가 아니라 컨텐츠를 건네줍니다.
rvalue가 아니라 lvalue입니다.
int *p=&a;
*p=0; // *p ==> lvalue

익명 사용자의 이미지

제가 무척 싫어하는 표기법중 하나를 사용하셨군요 ^__^;;

전 C의 포인터를 무척 좋아합니다. 편하거든요. 하지만 int *p=&a; 이렇게 하는 것 정말 싫어합니다.

물론 이게 int *p; p = &a;를 단 한줄로 줄여놓은 장점은 있지만 처음 포인터를 이해하려는 분들을 어지럽게 하는 문장입니다.

왜인지는 잘 아실 것입니다. C의 포인터에서 * 연산자의 사용은 두가지의 의미가 있습니다. 하나는 변수 선언시 포인터변수로 선언한다는 선언자로서의 의미, 또 하나는 포인터 변수가 지시한 주소의 값을 가져오라는 지시자로서의 의미 이렇게 말입니다. 그런데 int *p=&a;는 그런 개념을 어지럽게 만드는 요소가 있습니다. 그런 점이 어쩌면 서구에서 C가 아니라 PASCAL이 교육용 언어로 선택된 이유인지도 모르겠습니다.

익명 사용자의 이미지

제 생각에 K&R의 책은 초보에게 별로 적합하지 못한 책이라 생각됩니다. 컴퓨터 초보자 치고 그 책 처음 봐서 제대로 이해하는 사람 못 봤거든요.. 저의 초보시절을 생각해 보컨데... 초보시절에 객체가 뭔지, 주소가 뭔 주소를 말하는 건지, 객체의 주소가 뭘 말하는 건지, deref가 뭔지, 이런 것들을 이해할 수 없었거든요. 사실 저만 해도 컴퓨터에 있어서 주소가 뭔지 제대로 이해하는 데만 해도 1년이 걸렸습니다...-_-;;

The C Programming Language 같은 경우에는, C의 초기(맞죠?)에 나온 책일 것입니다. 그 당시에 그 책을 볼만한 사람들(대부분 어셈블리어나 로우레벨 프로그램 언어들에 익숙해 있을 것임)에게는 그 책 만큼 C에 대하여 명쾌하게 설명해 놓은 책이 없었을 것입니다. 그렇게 컴퓨터와 언어라는 것에 기본개념이 충분히 있는 사람에게는 The C Programming Language같이 좋은 책이 없죠.

사실 저같은 경우에는 포인터를 비교적 쉽게 이해한 편입니다. 어떻게 이해했는지는 정확하게 기억이 안 나지만, 그당시 다녔던 C언어 학원 강사님께서 참 친절하게 설명을 해 주셨던 듯 합니다...-_-;;
'보통 여기 배우다가 좌절하고 다시는 안 나오거든요...' 하는 설명과 함께....

초보의 입장에서는 int *a[] 같은 것은 쓸 일이 별로 없을 듯 합니다. 일단은 int *a 정도의 레벨에서만 사용을 하고, 거기서 약간씩 늘려 나가는 것이 좋을 듯 합니다.

아니면, 밑에 분들께서 말씀하시듯이, 처음에는 포인터 없이 프로그래밍을 하다가 불편함을 느낄 때마다 조금씩 더 사용하는 것이 더 좋을 듯 합니다. 왜 쓰는건지 이해를 못 하면 사실 배우기는 무지하게 힘드니깐요. '이게 도대체 어디 쓰이는거지?' 하는 의문을 갖고 있는 상태에서라면 제 경험상으로는 거의 못 배웁니다.

저같은 경우에 이런식으로 배운 게 function pointer입니다. 사실 왜 함수를 굳이 포인터를 갖아야 하는지 잘 이해를 못 한다면, 이해하는 데 문제가 있을거라 생각이 됩니다. 호출해야 할 함수를 따로 저장을 해 놔야 하는데 사실 int로 저장해 놓은 다음 switch/case 문으로 돌릴 수도 있습니다. 그렇지만 그렇게 한다면, 함수 하나 추가할 때 마다 코드를 이리저리 다 뜯어고쳐야 하고, 사용하려면 switch/case 문으로 지저분한 코드를 추가해야 하고... 이때 등장하는 게 function pointer이죠.

요약하자면, K&R 책은 참 좋은 책이고, C라는 언어 역시 컴퓨터에서 performance에 큰 부하를 안 주는 범위내에서 상당한 편의성을 갖고 있다는 데에는 동의하지만, K&R 책은 초보가 보기에 난이도가 너무 높다는 것입니다.

knight2000_의 이미지

제 생각도 같습니다.
이론적으로 완벽한 설명을 하고 있을 뿐, 쉽게 설명하는 책은 아닙니다.

논문 쓰면서 참고하기에는 좋더군요.
지금 느끼는 건데.... 역시 "명서"였습니다.

익명 사용자의 이미지

참고로 다양한 형태의 포인터가 존재하는 것은 스탭 이동시 안정성을 확보하기 위한 것입니다. (C가 어셈보다는 조금 고급언어라는 얘기지요.)

다시말해 포인터의 <++> 은 어셈으로 바뀐 코드에서는 <+1> 이 아니라 <+ sizeof(t)> 형태입니다.

예를들어
int *p;라고 정의했을때 p++과 p+=1, p=p+1은 같은 동작을 하지만, 내부적으로는 +4를 하게 됩니다. (궁금하시면 VC++에서 디버깅 모드에서 어셈 코드를 보시면 됩니다)
구조체 크기가 100바이트 일때, 구조체의 포인터는 100바이트 단위로 이동을 하므로 굳이 +100이라고 쓸 필요가 없죠. 오히려 이런 경우는 오동작하게 되겠죠.

익명 사용자의 이미지

포인터는 그냥 메모리 주소를 가리키는 변수 아닌가요?

말 그대로 지시자... -_-;;; 그럼 고운 하루...

익명 사용자의 이미지

JAVA에는 포인터가 없다는 말에 속아서.. -_-;
JAVA는 쉽겠지.. 했지만..

JAVA도 내가 포인터 변수를 못건드릴 뿐이지..
웬만한 변수 개념이 다 포인터인걸 보고 뒤집어졌더랬습니다.

정말로.. 포인터는.. 이해했다고 생각한 순간
또 모르겠더군요..

자료구조까지는 어떻게 어떻게 만들어쓰는데..

2차원 배열과 **, 3차원배열과 *** 쯤 가면..
아무 생각이 없어집니다. --;;

익명 사용자의 이미지

JAVA와 C는 내부적으로 같은 동작에 대해 표현하는 방법이 반대인것 같습니다. 포인터 하나야 반대로 써주면 그만이지만 더블 포인터라면??? 아무튼 C쪽에서 보면 그렇다는 얘기입니다. 내부적으로 처리하는 메모리 링크를 이해하지 못하면 JAVA도 만만치 않게 어렵죠. 공개된 내부 자료가 많지 않아서 개발자입장에서는 어느정도 추측만 할 수 있을 뿐.

익명 사용자의 이미지

더블 포인터, 트리플 포인터와
이차원 배열, 삼차원 배열은 완전히 다른건데,
다른걸 가지고 가셨으니 아무생각이 없어지는겁니다.

익명 사용자의 이미지

커니건과 리치의 The C language programming책에 포인터에 대한 설명이 젤 깔끔하게 나와 있는듯.
(C를 만든 사람들이 쓴 책이라서 모든 사용법이)

첨에는 메모리를 할당 할때 쓰다가,
소켓 프로그래밍 할때는 타입 케스팅 할때 쓰고,
좀더 가서 함수 포인터 까지 써주면,
상당히 유연한 코딩을 하게 되던데요.

처음에는 개념이 어렵고 이해가 안될수도 있는데,
C만 몇년 만지다 보니, 포인터가 뭐 특별하다는
생각은 없어지더군요.

힘내세요. 열심히 하면 언젠가는... 그날이 오겠죠.

익명 사용자의 이미지

Step by Step

컴퓨터 구조 -> 운영체제 ->
Gwbasic -> Assembly -> C

이렇게 생각하니깐 이해하기 쉽더군염

그리고 돈벌라고 생각않하고 재미로 할려다
보니.포인터가 눈에 확들어 오더군염...

지금도 제 마음속에 도사리고 있는
빨래 배워서 돈벌려고 하는 성급함
이게 가장...무서운 적이 더군염 ^^

익명 사용자의 이미지

포인터 ~ 주소?

그냥 레퍼런스?

그냥 레퍼런스로 이해하면 곤란한가요?
뭐 이것저것 복잡하게 사용하는 것이 아니면
그냥 레퍼런스 정도가 괜찮은거 같은데요.

그럼 왜 포인터를 사용하지? 포인터 사용의 장점은 뭘까? 바로 레퍼런스 라는 점이죠.
겁나게 복잡한 자료형을 주고 받을 때 그땐 간단히 int, char로는 안되잖아요? 그런대 바로 레퍼런스를 넘겨주면 동째로 넘어가니까 아주 깔끔해서 좋더군요.

-영희-

익명 사용자의 이미지

물론 그렇게 이해하셔도 되겠지만...

포인터는 call by reference와는 다릅니다.

통째로 넘어가는거와는 전혀 다른 개념인듯....

(C에서 포인터는 call by value임)

익명 사용자의 이미지

그리구...ref와 다르다니? 그건 무슨 소린지 모르겠네요.
int a = 0;
f(&a);

void f(int *v){
*v = 10;
}

맞는건가요? 이래서 call by value라 하는건가요?
그런데 결국 레퍼런스에 있는 값을 변경한간데???
이해가 안되네요. 역시 전 씨랑은 안친한가봐요..

그럼 call by ref는 뭐지??

-영희-

익명 사용자의 이미지

제가 알기로...
콜 바이 밸류는 값으로 넘기는 거,
콜 바이 레퍼는 주소로 넘기는 거.
C는 콜 바이 밸류이니 f(a)하면 a를 값으로
넘기게 됩니다.
a가 포인터라 해도 f(a)를 통해 넘겨지는 건
a의 밸류입니다.
그런데 a가 일반 변수일 때 f(&a)하는 경우에는
분명 함수 f로 주소가 넘어갑니다.
제 생각에는..., 그러므로 C가 콜 바이 밸류다,
레퍼다 하는 것은 학적인 분류 이상의 의미는
없다고 생각합니다.
C에서는 함수에 인수를 넘길 때 '분명' 값으로
넘기지만, 때로는 주소로도 넘길 수 있는 거
같습니다.
-내부적으로는 별 의미가 없는 얘기겠지만...

-톨-

익명 사용자의 이미지

결론부터 말하자면, C언에서는 call by ref를 지원하지 않고, call by value만 지원합니다. C언어에서 포인터가 중요한 이유도 이 때문이지요..

변수의 값만 넘겨줄 수 있기 때문에 변수의 주소값을 넘겨주어서 그 값을 통해 간접적으로 억세스하는 게 포인터의 한가지 용도입니다. 실제로 영희님이 사용하신 소스의 v변수는 a의 주소값만 가질뿐 a는 아닙니다.

call by ref
라고 함은 a와 v가 이름만 다를뿐 같은 변수라는 겁니다.

' 장미는 그 이름이 장미가 아니어도 분명히 장미이다. '

call by ref는 C++에서야 비로소 지원되기 시작했습니다. 이런 형식입니다.

f(a);

void f(int& a)
{
a = 10;
}

reference variable 임을 나타내는 &를 이용하여 ( 포인터값을 얻는 연산자와 무관합니다. ) a와 v를 동일한 변수와 매핑합니다. 따라서 굳이 *연산자가 불필요하지요.

call by ref의 편리함은 겉으로 포인터를 가려준다는 점이지요. Java에서는 객체에 대해서는 반드시 call by ref로 이루어집니다. 따라서

Object aObject
func(aObject);

func(Object mObject)
{
mObject = 'newly value';
}

이렇게 하여도 aObject는 수정됩니다.

reference variable 사용함으로 자바는 '당당히' 포인터를 제거했다고
'구라'치는 거겠지요.. ^^;

익명 사용자의 이미지

조금 이상한 듯 싶네요. 만약에

int func(int* param) {}

이런 함수가 있을 때 이걸

int* a;
a에 메모리 할당 후
int b = func(a);

하면 func함수엔 메모리 값이 call by value로 넘어가지만 func 안에서 *param으로 호출해서 *param의 값을 변경하면 *a의 값도 바뀌기 때문에 *a 입장에서는 call by reference인 셈이 되죠. a입장에서는 그냥 int 넘어가는 거나 마찬가지니 call by value로 볼 수도 있지만 의미론적으로는 call by reference가 맞습니다.

call by reference란 게 딴 게 아니고 주소값만 넘겨주면 함수 안에서 그 주소값에 있는 값을 찾아서 작업을 하겠다는 것입니다. 위의 경우에 a를 넘겨주면 a값에는 메모리번지가 저장이 되어 있는데 이 값의 copy가 func에 넘어가서 func 안에서는 *param을 호출하면 *a를 호출하는 거나 같기 때문에 프로그래머 입장에서는 call by reference의 목적을 잘 달성할 수 있는 셈이죠. 물론 C++의 레퍼런스에 비해 코드가 좀 조잡하지만요-_-

설명이 좀 조잡한데-_- 간단히 말씀드리면
int *a 와 같이 선언하면
a에는 메모리 번지값이 저장되고
*a하면 그 번지 내의 실제값이 나오죠.

그냥 a하고 쓰면 메모리값이 저장된 일반 변수랑 똑같이 작동합니다.

두 값을 각각 찍어보면 감이 올 겁니다.

익명 사용자의 이미지

어려워서 잘은 모르겠지만 자세한 설명 고맙습니다.

-영희-

익명 사용자의 이미지

그렇게 본다면 int i의 i도 실제로는 i의 값이 저장된 곳을 가리키는
레퍼런스일 뿐입니다. 컴파일러가, 그리고 로더가 어떻게 동작하는지를
생각해 보세요. 포인터를 없앴다, 아니다는 주소를 직접 조작할
수있도록 하는(그리고 많은 에러가 양산되는) 것을 없앴다는 것입니다.

익명 사용자의 이미지

그런가요? 제가 잘 몰라서~
그런데 통째로 넘긴다는 표현은 그냥 사용하기 편하단 것으로,
물론 넘기는게 아니죠. 그냥 그곳의 값을 사용하겠다는 거죠.

익명 사용자의 이미지

역시 다들 그렇군요...

먼저 어셈을 하게 되면

포인터는 정말 간단히 이해되죠...

익명 사용자의 이미지

난 치환이라는 개념을 써서 이해했는데 첨하는 사람들한테는 그게 더 쉽다고 생각이 드네요.
예를들어
int *a; 정수 포인터 a에서 *a를 A로 치환해서
int A; 생각하고 쓰면 되는데요.
int 변수 이형태는 잘 이해하잖아요
글치만
int *변수는 왠지 골치아프잖아요.
차라리 치환을 해서 생각해버리는게
첨할때 쉬울꺼라고 생각을 합니다.
그렇게하다보면 치환을 안해도 될 수준이
될것이고 더블 포인터나 트리플 포인터
그 이상이 되어도(누가 쓸려나) 문제없을
겁니다.

익명 사용자의 이미지

음 제 생각은 조금 틀린데여
c 에서는 int *a; 라구 표현하지만, c++ 에서는 int* a; 라구 많이 쓰쟎아여,

그래서 int type 인 *a가 아닌 int* type 인 a 가 더 나은것 같네여...

그래서 치환을 하자면 int* a; 일때 int* 를 INT로 하면 INT a; 라구 표현 해보는것두 괜찮을것 같군요. ^^

익명 사용자의 이미지

자그럼
C에서
int *i, j;

int *i;
int j;
와 같은 뜻이죠?

c++에서의
int* i, j;

int* i;
int* j;
일까요?

int* i;
int j;
일까요?

g++에서 컴파일해보면,
후자로 인식합니다.
그러니깐 int* 를 타입으로 생각하게 되면,
더욱 헷갈리죠.

굳이 typedef를 하실려면,
int*를 INT보다는 pint나 intp 가 덜 헷갈리겠죠?

익명 사용자의 이미지

역시나 어셈블리 언어를 하신 분 들은 포인터 그냥 잘 넘어 가시는 군요.
저도 어셈을 먼저하고 C를 접하니 포인터 그거 간접인덱스 아닙니까?

그렇다고 어셈을 먼저 하라고 권하기는 힘들지만 최소한 어느 정도 수준에 이르려면 역시 기계의 구조를 이해하는 것은 필수로 여겨집니다.

즉 포인터의 이해는 언어의 문제가 아니라 어느 정도의 기계구조를 이해하는 것이 첩경이라 생각됩니다.

익명 사용자의 이미지

저두 어셈을 먼저하고 C를 해서 그런지
포인터 이해가 쉽더군요..

익명 사용자의 이미지

저두요
하지만 ** 이중 포인터는 어렵게 알았습니다.

익명 사용자의 이미지

저는 'C 포인터 정복' - 김영훈저
을 읽고 포인터를 이해했습니다.

감히 포인터에 관한책으로는 최고입니다.

그 책에보면 포인터를 개념적으로 설명하더군요. 물론 그 다음에 메모리 구조에 대해서 설명하구요.

컴퓨터 언어를 사람이 이해할수 있을려면 사람의 언어로 알게끔 해야 합니다.

그런 점에서 C++은 C보다는 포인터 사용이 적더군요. 일부는 참조자로 대체하니깐요...

언어는 도구라 생각하시고 필요할때 쓴다라고 보시면 좋습니다.

Renn의 이미지

중2때부터 독학으로 C를 공부하였죠. 덕분에 포인터에서 애를 많이 먹었는데... 무엇인지 제대로 알지 못했죠.

게임 프로그래밍을 공부하게 되면서 조금 눈을 뜨게 된 것이 있었는데, 특정 포인터에 메모리 할당을 해서 배열처럼 참조하는 것이었죠. (당시 도스라서 배열 크기에는 한계가 있었죠)

*(a+i) == a[i]

포인터에 i를 더한 곳의 데이터는 배열에서 i번째 원소랑 동일하다 라는 것을 머리에 박았죠. (물론 틀린 말이긴 합니다만, 충분히 써먹을 수 있죠) 그래서 약 1년 정도 이런 지식으로 계속 써먹었습니다.

그 다음에 포인터를 진정 이해할 수 있었던 부분은 링크드리스트. 소스를 봐도 설명을 봐도 잘 이해가 안갔지만 링크드리스트의 구조를 그림으로 표현해 놓은 설명서를 보고 갑자기 눈을 떴습니다. 여러개의 메모리를 잡아놓고 한 포인터가 이 메로리를 왔다 갔다 하는것을 보고 이해할 수가 있었습니다.

물론 개인차가 있겠지만, 계속 써오다 보면 뭔가 눈에 보이게 되는것 같습니다. 만화 같은 것에서 운동선수나 기타 뭔가를 열심히 노력하는 사람에게는 헛점이 눈에 보이는 것 처럼 말이죠. :)
--
Seo, Hee-Seung.
http://anitype.net/

익명 사용자의 이미지

개인적으로는 어셈블리를 먼저 배워서 그런지 포인터를 상당히 쉽게 배었습니다. 어셈 입장에서 보면 주소 연산을 할 일이 많은데, 그게 C입장에서 보면 '포인터'죠.

포인터의 포인터와 함수의 포인터는 LinkedList를 만들면서 확실하게 감을 잡았고요. 요건 어셈이랑 개념이 조금 달라서.

눈에 보이는 백설표마크에 현혹되지 말고요, 해당 시점에서 원하는 것이 <값>인가 <어드레스>인가만 판단해서 코딩하면 거의 실수를 안합니다. 도움이 되었으면 하네요.

익명 사용자의 이미지

어셈블러..

링크드리스트..

요 두가지넘때문에 이해가 빨랐습니당..

Heissenberg의 이미지

글쎄요.. 저도 한동안 삽질했던 기억이 나네요..
포인터를 잘 사용하는 법이라고 하면 일단 포인터를 덜 쓰면서 프로그래밍하는 방법이겠지요.
한번씩 사용하면서 포인터에 대한 감이 잡히기 시작하고, 다른 사람들이 사용한 포인터를 보면서 조금씩 익혀 가는 거겠지요..
그리고 사실 포인터를 복잡하게 사용하는 경우는 드뭅니다. 보통 포인터의 포인터 정도.. 그 정도가 많이 사용하면서도 가장 복잡한 형태가 아닌가 합니다.
많이 짜보면서 이해하세요..

익명 사용자의 이미지

포인트는 어떤 Type 의 주소를 값으로 가지는 변수라고 그냥 생각합니다.

관계없는 말이지만 전 타 언어를 선택하지 못하고 계속 C/C++ 만 사용하는 이유가 포인트와 전처리기 때문입니다.

일부 사람들은 포인트와 전처리기(매크로)를 욕하는 이도 있지만, 전 그거 없으면 플밍 못할 정도 ㅡㅜ

익명 사용자의 이미지

저는 포인터를 포기하고서야 포인터를 이해하기 시작했습니다.

무슨 말이냐구요? 포인터 사용하기 힘들면 우선 그냥 일반 변수 사용하세요. 문자열 처리다 뭐다 다 그냥 배열형 문자열 변수 몇개더 선언하구, 변수 몇자리 선언하구 그렇게 프로그램 작성하세요. 구조체 포인터 사용하기 힘들면 그냥 구조체 사용하세요. 그냥 편한 것 사용하는 것입니다. 그러다보면 어느 순간엔가 갑자기 어라 이런 경우에는 이넘의 주소만을 알고서 처리하는 것이 쉬울텐데 하는 경우가 생겨납니다. 그때 포인터 사용하십시오. 포인터 없어도 프로그램 대부분 작성 가능합니다. 포인터 없이 만들어진 소프트웨어도 충분히 고급스럽습니다. 단지 포인터는 없는 것보다 있는 것이 쓰기 쉽기때문에 사용하는 것입니다. 저는 그렇게 생각합니다.

BY 가랑비

lovehis의 이미지

동감....

포인터 모른다고 프로그램을 못짜는 것은 아님니다.

단지 프로그램짜는 방법을 모르는 것일뿐...

소위 말해서 중고급의 문법(이렇게 말하는 것이 우습지만)은 대부분의 경우에서 단지 프로그램을
편하게 작성하기 위함이지, 없으면 못짜는 것은 아님니다...

불편함을 알아야지 편한것을 이해 할 수 있습니다.
--
늘...

eric의 이미지

불편함을 알아야지 편한것을 이해할 수 있다..

전적으로 동감입니다. :-)

익명 사용자의 이미지

그렇죠....

2002년에도 c랑 c++이 있었다니 일단 저는 2005년생입니다의 이미지

아니 근데 요즘에는 생성형 AI 예를 들어서 ChatGPT 이런것들이 너무 나와서 c랑 c++을 공부하는것이 무의미해 보이는데 c랑 c++을 공부해야하는 이유가 있을까요??

익명 사용자의 이미지

AI 프로그래밍에 쓰이는 파이썬, 프레임워크인 tensorflow 등이 모두 C++ 로 만들어져 있죠.

페이지

댓글 달기

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