1) 지식 창고는 본인이 작성한 콘텐츠(팁/노하우/리소스/강좌 등)을 무료 혹은 가상화폐인 납포인트를 통해 공유하는 공간입니다.
2) 본인이 작성한 콘텐츠에 대해서만 지식 창고에 등록할 수 있으며, 저작권에 위배되는 콘텐츠는 사전경고 없이 삭제될 수 있습니다.
3) 콘텐츠 구매 및 첨부파일 다운로드는 회원그룹 '연구원' 이상 가능하오니, 경험치를 쌓아 진급한 후에 이용 부탁드립니다.
4) 무료 콘텐츠의 본문은 구매절차 없이 즉시 이용할 수 있으며, 판매 납포인트가 있는 콘텐츠는 구매 후 이용할 수 있습니다.
5) 콘텐츠 판매에 따른 납포인트 수익은 지정한 비율(50%)에 따라 판매자에게 지급하며, 납포인트 수익을 통해 진급을 빨리할 수 있습니다.
6) 구매 후 평가를 하면 구매 납포인트의 20%를 돌려 드립니다.
판매자 | 프리미엄 | 판매 납포인트 | 무료 | 평점 | 0점 / 총 0명 참여 |
---|
***************************< 캠퍼스 C 강좌 >******************************
[제목] :
[코드] : campusc1-011 (초급)
[교재] : CAMPUS C (초급, Third edition) [출판사 : 책과스승]
[알림] :이 파일은 "캠퍼스 C"에서 모든 분께 공개한 "초급 강좌"입니다.
이 [알림]의 내용을 지우지 않는다면 누구에게나 임의로 복사해 줄 수
있습니다.그러나 이 강좌 내용에 대한 저작권은 "캠퍼스 C"에 있습니다.
[연락처] : 605-8662 (서울) ("캠퍼스 C", 도서출판 "책과 스승")
천리안 : go campusc
나우콤 : go lcampc
하이텔 ID : campusc
****************************<< 목 차 >>************************************
<1> 포인터에 관계된 표기법
1> '*' 의 의미 3 가지
2> '&' 의 의미 2 가지
3> a = b 에서 서로 타입이 같아야 한다.
4> 배열과 포인터는 넘나든다.
5> 포인터 연산
**************************< 내용 시작 >********************************
<1> 포인터에 관계된 표기법
***********************************************************************
1> '*' 의 의미 3 가지
---------------------------
C 프로그램에서 나타나는 소령마크(*)에는 3가지의 의미가 있습니다. 그것은
주로 선언되는 "위치"와 "문장의 형태"로 구별이 됩니다. 다음을 봅니다.
char ch, *point_ch; /* <--- [ 의미 1 ] */
main()
{
int song_no, *ma_dangbal /* <----[ 의미 1 ] */
int a,b,c;
a = b*c /* <--- [ 의미 2 ] */
a *= b; /* <--- [ 의미 2 ] */
ch = 'a';
point_ch = &ch;
putch('a');
putch(ch);
putch(*point_ch); /* <--- [ 의미 3 ] */
printf(" %d", *ma_dangbal); /* <--- [ 의미 3 ] */
}
포인터 의 내용 자체도 다소 정신이 없기 때문에, 본격적인 내용에 들어가기
전에 먼저 "형태적"으로 의미의 차이를 구별하는 것이 필요합니다.
----------
[의미 1]
----------
위 프로그램에서 쓰는 첫번째의 의미는 "변수 선언 하는 부분"에서
나타나는 소령마크의 의미입니다. 즉,
------------------------
1. main()함수 위나,
2. 함수 내부의 처음 부분
------------------------
이지요. 의미는 지난 번 공부한 바와 같이 "의 집을 가르키는 집" 이란 것
입니다.
지난번 문제를 낸 바 와 같이 IBM-PC 기종에서는, 모든 포인터 타입의 변수
는 2 바이트 크기를 갖습니다.
아래와 같은 프로그램으로 실험을 해보면 알 수 있습니다.
main()
{
char *pp1;
int *pp2;
long *pp3;
printf(" %d %d %d", sizeof(pp1),sizeof(pp2),sizeof(pp3));
/* 결과 : 2 2 2 */
}
이건 당연한 얘기지요. 누구네 집을 가리켜주는 집은 손가락 하나
들어갈 크기만 있으면 될 뿐이지, 큰 대장집을 가리키는 손가락이라고 해서
더 커야할 이유가 없는 것 이지요. 따라서 Turbo-C 에서는 손가락의 크기를
전부 2 바이트 크기로 통일 했습니다. (메모리 모델에 따라 4바이트로 될 수
도 있지만 일단 여기서는 전부 2바이트로 취급함)
그럼 왜 하필 2 바이트로 결정했을까요 ? 한 바이트로 결정하면 어
떤 문제가 생길까요? 짐작 하다시피 한 바이트는 0 부터 255 번지 까지
밖에 알려주지 못합니다. 크기가 너무 작지요. 그럼 4 바이트로 하면 어떤
가요 ? 그건 (32 bit = 4 Giga) 너무 크지요.
크다고 나쁠건 없지만, 2 바이트란, 얘기를 잠깐 한적이 있지만,
"세그먼트"와 같은 크기 입니다. 예를들어 데이타 세그먼트는 크기가 64K 입
니다. 이 크기를 가리키는 CPU의 "세그먼트 레지스터"가 두 바이트로 되 있
다는 겁니다.([20,23쪽]) 참조). 즉 이 세그먼트 레지스터의 크기가 int형과
크기가 같고 지금 얘기하는 포인터 와 크기가 같습니다. 이건 무얼 의미하는
가 하면 "포인터" 하나만 있으면 최소한 "세그먼트"내의 모든 집 주소를 가
리킬 수 있다는 뜻입니다. 아주 안성맞춤 이지요. 우연히 그렇게 된게 아니
고 일부러 그렇게 맞추었으니 딱 맞을 밖에요.
따라서 혹시 어떤 영역이 64K 를 넘어가면, 포인터 변수 하나로는
도저히 그 부분을 가리킬 수 없습니다. 이건 마치 60층 짜리 고가사다리차가
63 빌딩의 꼭대기 까지 닿지 못하는 것과 똑같은 개념입니다.
이런 경우는 포인터에게는 "너무 먼거리" 아닙니까 ? 이걸 영어로는
"far" 라고 합니다. 즉 "너무 먼 !"이라는 뜻이지요. [375쪽]을 보면 "그래
픽 함수" 그룹이 있습니다. 나중에도 나오겠지만, 여기에 나오는 함수들을
보면 (예를 들어 첫번째의 arc() 함수설명 부분 [396쪽]을 보면 "void far
arc(.......)"에 "far"라는 단어가 나옵니다. 이 far가 지금 얘기하는 너무
먼 거리에서 대답이 온다는 뜻입니다. 이런 경우는 포인터 변수 두개로 받아
야지요.
이런 자세한 얘기는 지금 얘기할 단계는 아닌것 같고, 지금 하고자
하는 얘기는, "포인터는 좌우간 2바이트의 크기(int 크기)를 갖는다"로 생
각하기로 합니다.
크기개념을 위해서 조금 더 예를 들면,여러분 컴퓨터에 1 Mega의 메
모리 가 있다고 칩시다. 1 M 는 정확히 1024K 이고 이것을 64K(포인터
크기)로 나누면 16 입니다. 즉 포인터 16 개가 연속적으로 가르켜야 도달 할
수있는 거리입니다.
---------
[의미 2]
---------
이것은 아시다시피 곱하기 입니다.
a = b*c
a *= b; /* a = a * b 와 같음 */
이것은 상식적으로 두개의 변수가 필요합니다. 그래야 a x b 를 하지요. 이
와같이 두개의 변수가 필요한 연산자를 우리는 "2항 연산자"라고 부릅니다.
[88쪽]의 표에 이 부분에 표시를 해 놓으세요. 그리고 이와 비교가 되는게
단항 연산자입니다. 이것은 변수가 하나만 필요한 것이란 의미 입니다.
표를 보면 "이항 연산자"와 "단항 연산자"에 각각 하나씩 소령마크(*) 가 있
지요 ? 지금 얘기하는 "곱셈"의 의미를 제외한 [의미 1]과 [의미 3]이 전부
단항 연산자 얘기 입니다.
-------------
[의미 3]
-------------
이것은 아주 중요한데 반드시 함수 내부의 "실행문"에서 나타납니다.(변수
선언 할 때가 아니고) (중요)
printf("%d", *ma_dangbal); /* <--- [ 의미 3 ] */
C 에서는 일반적으로 포인터(마당 발)네 집에 찾아가는 이유가,
항상 아래와 같은 둘 중의 하나의 값을 알아보기 위해서 입니다.
---------------------< 한국말 질문 >---------------------
<질문 1> "당발 아! 너 지금 몇 번지 가리키고(갖고) 있냐 ? 찍어봐 !"
<답> "1번지 !"
<질문 2> " 그 주소에 살고 있는 사람이 누구냐 ? 찍어봐 !"
<답> "서대지"
위에서 "찍어봐" 라는건 print 해보라는 겁니다. 내 표현이 가끔 상
스러울 때가 있어서 여기서도 "도끼로 ..." 따위의 이상한 연상을 하면 안됩
니다.
이걸 C 말로 표현하면 다음과 같습니다.
---------------------< C 말 질문 >---------------------
<질문 1> printf("찍어봐 %x", ma_dangbal);
<답> 0x0001
<질문 2> printf("찍어봐 %x", *ma_dangbal);
<답> 0xffff (이건 임의의 값임)
이것도 역시 처음보는 사람은 의미가 "마음에 와 닿지 않겠지만"
<한국말 질문> 과 < C 말 질문>을 비교해 보면서 그 의미를 "외워야" 합니
다. 하지만 이건 무작정 외우는게 아니라 법칙입니다.
영어를 빨리 배울려면 가능한 영어를 쓰는 나라에 가서 사는 것이
제일 좋은 방법인것 처럼, 우리도 C 말을 빨리 배우려면 가급적 기계의 입장
이 되어야 합니다.
이제 우리 기계 입장이 되서 좀더 사실적으로 느껴볼까요. 당발 씨
집 문패는 이렇습니다.
----------------------------------
가수 *마 당발
----------------------------------
이걸 C로 써 놓으면 다음과 같이 보이는 것이지요. (가수 대신 int 형으로
바꿉니다)
main()
{
int *ma_dangbal;
.
.
.
}
이제 문을 열고 들어가지요. 아다시피 한 바이트는 8 비트로 이루어
져 있고, 이집은 포인터로서 두 바이트 이기 때문에(내부에서 두채를 텄다)
전구 16개가 나란히 있는 모양 입니다. (이건 실제 메모리 내부 개념입니
다.)
이 집의 전구가 전부 꺼지고 LSB(제일 오른쪽 비트) 만 켜있다고 합
시다. 이 값은 0000 0000 0000 0001 이고 16진법으로 0x0001 입니다. 우리는
이제 0x0001 호에 가수가 살고 있다는 것을 알았습니다.
즉 다음 질문에 대한 답입니다.
<질문 1> "당발 아! 너 지금 몇 번지 갖고 있냐 ? 찍어봐 !"
<질문 1> printf("찍어봐 %x", ma_dangbal);
<답> 0x0001
이제 가수가 사는 0x0001 번지로 가봅시다. 문패가 다음과 같습니다.
--------------------------------
< 0x0001 호 >
가수 서대지
int so_daeji
--------------------------------
이제 <질문 2> 입니다.
<질문 2> " 그 주소에 살고 있는 사람이 누구냐 ? 찍어봐 !"
<질문 2> printf("찍어봐 %d ", *ma_dangbal);
<답> 0xffff (서대지가 아님)
이 답은 서대지가 아닙니다.우리는 지금 기계입장 이기 때문에 한국
말이나 영어 를 읽지 못합니다.위의 문패 같은 것은 사람들 끼리 읽기 좋으
라고 붙여준 것이지 기계(여기서는 CPU) 가 알 리가 없습니다.
이제 문을 열고 들어갑니다. 불이 전부 켜져 있군요. 이제 알았다 "
아하 ! 가수 0xffff 구나"
좀더 유명한 가수 이름을 들려주지 못해 미안합니다. 그러나 우리는
지금 기계이기 때문에 서대지같은 이름을 붙여줘 봐야 그 이미지를 알지 못
합니다.다만 가수번호 0xffff 가 산다는 걸 확인 할 뿐이지요.
결국 <질문 2> 의 대답은 0xffff입니다. 이제 다시 질문을 보면
printf("찍어봐 %d %d", ma_dangbal, *ma_dangbal);
<문1> <문2>
앞으로는 위의 <문1> 을 다음과 같이 말합니다.
"ma_dangbal 의 값을 찍어보라" --> 0x0001
위의 <문2> 를 말로 하면
"ma_dangbal 이 가리키는 주소의 값을 찍어보라" --> 0xffff
말이 더 이상한 것 같은데 가능한 의미 자체를 연상 하세요. 이걸 굳이 공식
화 시켜보면 다음과 같습니다.
ma_dangbal <-- ma_dangbal의 값
*ma_dangbal <-- ma_dangbal의 값 의 주소의 값.
------------
( '*' 과 같다)
이 부분은 뒤에 더 정확히 나오고 여기서는 [의미 1]과 [의미 3]의 "표기법"
을 서로 구별 하는 일이 중요 합니다.
<문제> 다음을 컴파일 시키지 말고 눈으로 값을 찾아보세요
main()
{
char my_state[] = "I am hungry";
char *ma_dangbal ;
ma_dangbal = &my_state[0];
printf(" %d", ma_dangbal) --> 이 값은 컴파일러가 알아서 결정
printf(" %c", *ma_dangbal); --> ?
ma_dangbal++;
ma_dangbal++;
printf(" %c", *ma_dangbal); --> ?
}
여기서 나오는 "증가(++)"의 의미를 자세히 이해 하려면 [119쪽](새교재
[154쪽]의 "포인터의 증가"를 읽으세요.
-----------------------------------------------------------------------
2> '&' 의 의미 2 가지
-----------------------------------------------------------------------
'&' 에도 의미가 두개가 있습니다. 아래를 봅니다.
main()
{
int so_daeji, *ma_dangbal;
int a,b,c;
a = b & c; /* <--- [ 의미 1 ] */
a &= b; /* <--- [ 의미 1 ] */
printf("%d ", &so_daeji); /* <--- [의미 2] */
ma_dangbal = &so_daeji; /* <--- [의미 2] */
printf("%d", &ma_dangbal); /* <--- [의미 2] */
}
--------
[의미 1]
--------
이건 연산자에서 다룬 "비트 AND" 입니다. 이것은 반드시 두개의 항
이 필요합니다. [88쪽]의 표를 보세요. "2 항 연산자"의 의미를 아시겠지요.
--------
[의미 2]
--------
이건 지난 시간에 언급한대로 & --> "의 주소" 의 뜻입니다.
ma_dangbal = &so_daeji;
이것을 말로하면" so_daeji<의 주소>를 ma_dangbal 에 넣어라" 입니다.
<문> printf(" %d", so_daeji);
<답> 0xffff ( 위 * 예 참조)
<문> printf(" %d", &so_daeji);
<답> 103호 ( 아래 그림 참조)
---------------------------
< 103 호>
가수 so_daeji
---------------------------
여기서 주소 <103 호 > 따위는 컴파일러가 알아서 할당해 줍니다. 우리는 그
정확한 주소를 알아야 할 필요는 없습니다.
<문> 다음 표현 에서 말이 안되는것은 ?
main()
{
int so_daeji, *ma_dangbal;
printf("%d", so_daeji); /* 1번 */
printf("%d", &so_daeji); /* 2번 */
printf("%d", *so_daeji); /* 3번 */
printf("%d", ma_dangbal); /* 4번 */
printf("%d", &ma_dangbal); /* 5번 */
printf("%d", *ma_dangbal); /* 6번 */
}
<문> 바로 위 <문제>에서 찍은 결과가 "주소" 인지 아니면 "실제 값" 인지
구별하라. 즉 ,
/* 1번 */ --> 값
/* 2번 */ --> 주소
.
.
-----------------------------------------------------------------------
3> a = b 에서 서로 타입이 같아야 한다
-----------------------------------------------------------------------
대입 연산자 '=' 를 보면 우리는 항상 두가지 의미를 동시에 생각해야 합니
다.즉
---------------------------------------------------
1. 기본 뜻은 "오른쪽 값"을 "왼쪽"에 넣으라는 것이고
2.그리고 "양쪽의 변수 타입이 같아야 한다" 입니다.
---------------------------------------------------
첫번째 뜻은 기본적으로 알 것이고, 이제부터는 두번째 의미가 더욱
중요하게 등장을 하는데 다음을 봅시다. "=" 을 기준으로 어떤 값들이 서로
대칭을 이루는지 눈여겨 봐야 합니다.
main()
{
int so_daeji,jo_yongpil, *ma_dangbal;
so_daeji = 0xffff; /* * = * */
ma_dangbal = &so_daeji; /* & = & */
jo_yongpil = *ma_dangbal; /* * = * */
so_daeji = jo_yongpil /* * = * */
}
위에서 주고받는 내용이 "주소" 이면 "&" 로 쓰고 "값"이면 "*" 로
표기했습니다. 이중에서 특히 so_daeji = 0xffff; 에서 "0xffff"는 "값"에
해당한다는걸 유심히 보세요. "주소"를 막바로 이런식으로 넣지는 않습니다.
그리고
-------------------------------------------------
반드시 값은 값끼리, 주소는 주소끼리 주고 받는다.
-------------------------------------------------
라는 사실을 주목 하세요. 이건 너무도 당연한 사실이지만 앞으로 많은 사람
들이 눈 뜨고도 그걸 구별 못하는 수가 있을겁니다. 이 중요성을 항상 인식
하고 있어야 합니다
그리고 이 기회에 다시한번 [88쪽]의 대입 연산자 부분을 읽고, "="의 양쪽
은 시소놀이 할 때 처럼, "크기"와 또 지금 얘기한 "내용( * = * 따위)"이
"대칭"이 되야 하는 걸 정리해서 기억해야 합니다.
-----------------------------------------------------------------------
4> 배열과 포인터는 넘나든다.
-----------------------------------------------------------------------
앞으로 차차 나오겠지만 컴파일러가 배열과 포인터를 취급하는 방법을
조금더 이해하면 이 둘은 아주 비슷하다는 것을 알 겁니다. 따라서 배열과
포인터는 서로 넘나들면서 변신을 할 수도 있는데 , 이것도 역시 기본 내용
을 이해하는게 중요합니다. 지난번 예를 다시 보면.
main()
{
char *ma_dangbal = "hello"; <--- 포인터로 선언
char rambo[] = "RAMBO"; <--- 배열로 //
printf(" %c ", ma_dangbal[0] ) <--- 배열로 사용
printf(" %c ", *rambo ) <--- 포인터로 사용
}
위의 표현들은 다 정확한 것인데, 그 유명한 "마 당발"씨가 포인터
로 선언되었음에도 불구하고 배열로 쓰이고 있는걸 보세요. 배열인 "rambo"
도 포인터로 쓰이고 있습니다. 이 내용을 이해 하기 위해서는 하나 외울게
있습니다. 즉 위 예문에서
--------< 중요 >--------
rambo 는 &rambo[0] 이다.
------------------------
다시 말해서 배열명이 "[]" 를 떼버리고 돌아다니면 그건 자기 배열의 "선두
번지"를 의미 한다는 것입니다. 즉 예를 보면
main()
{
char rambo[] = "Happy";
char *pp;
pp = &rambo[0]; <-- 아래와 같은 표현임
pp = rambo; <-- 위와 같은 표현임
}
printf("%p %p", &rambo[0], rambo); <-- 주소 결과가 같음
printf("%p %p", pp, pp2); <-- 당연히 결과가 같음
printf("%p %p", pp, &rambo[0]); <-- 당연히 결과가 같음
printf("%p %p", pp2, rambo); <-- 당연히 결과가 같음
}
%p 타입은 16진수로 주소를 찍어 보는 방법이고, 위에서 얘기 하고 싶은건
다음의 "주소" 3개가 똑같다는 것입니다.
1. rambo
2. &rambo[0]
3. pp
그러면 똑같은 예로 "값"을 찍어봅시다.(이제 &rambo[0] 은 퇴장 시킨다)
main()
{
char rambo[] = "Happy";
char *pp;
pp = rambo;
printf("%c %c", *pp, *rambo); <-- 값 결과가 같음
}
위 프로그램이 얘기 하는것은 지극히 간단합니다. 즉
------------
pp = rambo
*pp = *rambo
------------
입니다. 말로 하면
---------------------------------------
"배열 rambo의 선두번지를 pp에 넣어준다"
"그 앞에 각각 소령 마크 '*'를 붙여준다"
---------------------------------------
뜻을 따지려면 저도 정신 차리고 생각을 해봐야 합니다. 하물며 이런 표현을
처음보는 분이라면, 그 "의미"를 생각하기가 골치 아플지도 모르겠습니다.
하지만 지금은 그런걸 생각할 필요는 없고 "="을 기준으로 양쪽 "타입"이 같
은지만 보면 됩니다. 즉 위의 경우는
-------------
& = &
* = *
-------------
이라는건 아시겠지요 ? 여기서 문제를 내볼까요 ?
<문> 아래에서 (바로 위의 표현을 복사 한겁니다) pp와 rambo 어느게 포인터
고 어느게 배열인지 형태로 구별할 수 있겠나요 ?
------------
pp = rambo
*pp = *rambo
------------
<답> 이름으로 짐작은 가지만 형태는 전부 포인터 쓰는 형식 이에요.
여러분은 어느새 배열이 포인터로 둔갑한 것을 보고 있는 겁니다. 다음의 예
를 보지요.
main()
{
char rambo[] = "Happy";
char *pp;
pp = rambo;
printf("%c", rambo[0]); <-- 값 이 같음
printf("%c", *rambo); <-- 값 이 같음
printf("%c", *pp); <-- 값 이 같음
printf("%p", &rambo[0]); <-- 주소 결과가 같음
printf("%p", rambo); <-- 이건 공식임(위와 같음)
printf("%p", pp); <-- 주소 결과가 같음
}
위의 내용이 이해가 되시면 배열 --> 포인터로 바뀌는건 확실히 아셨다고
생각해도 됩니다.
"포인터 --> 배열"로 바뀌는 것도 위와 똑같은 이유로 표현이 같아
집니다. 나중에 또 얘기할 기회가 있을것이고 일단은 우리가 배열과 포인터
의 표현이 같아질 수 있다는 것을 알았으므로 다음의 표를 이해 할 수 있을
겁니다.
다음과 같이 선언 되었다고 하고,
main()
{
char rambo[3];
char *p = rambo;
}
이 표현들은 전부 같은 의미다.(중요)
--------------------------------------------------------------------
rambo[0] , *rambo, *p , p[0] <-- 100 번지 라고 치자.
rambo[1] , *(rambo + 1) , *(p + 1) , p[1] <-- 101 번지
rambo[2] , *(rambo + 2) , *(p + 2) , p[2] <-- 101 번지
rambo[3] , *(rambo + 3) , *(p + 3) , p[3] <-- 101 번지
--------------------------------------------------------------------
오늘 우리는 맨 윗줄만 대표적으로 예를 들었으나 위의 일반적인 형태를 눈
여겨 보세요.다만 주의 할것은
------------------------------------------------------------
포인터 = 배열 (배열명을 포인터 변수에 대입)할 수는 있으나
배열 = 포인터 (포인터 변수를 배열에 대입)할 수는 없다
-------------------------------------------------------------
예를 들어 다음과 같이 선언 되었다면
main()
{
char rambo[3];
char *p ;
p = rambo; <-- (맞다)
rambo = p; <-- (틀림)
}
위에서 포인터 P는 두 바이트의 집을 갖고 있습니다. 거기다 &rambo[0]을 넣
는데는 아무런 문제가 없습니다. 그러나 " rambo "라는 표현은 rambo[0]의
주소를 말하는 "상수 값"입니다. (예를 들면 100 번지 같은) 즉 번지수를
넣어줄 수 있는 방을 갖고 있는 표현법이 아니지요. 즉
----------------------------------------------
rambo[0] <-- 에는 한 바이트를 넣을 수 있다
&rambo[0] <-- ? (넣을 집이 없다)
----------------------------------------------
<문> [180쪽] (예제 3)의 결과를 찍어보세요.
<문> 다음의 결과를 찍어보세요.
#include <stdio.h>
main()
{
char ss[] = "abcde";
char *p = ss;
int i;
for(i=0; i < sizeof(ss); i++)
putchar(ss[i]);
putchar('\n');
for(i=0; i < sizeof(ss); i++)
putchar(p[i]);
putchar('\n');
}
-----------------------------------------------------------------------
5> 포인터 연산
-----------------------------------------------------------------------
포인터에 1을 증가시키는 동작은
-----------------------------------------------------
"번지값이 1" 만큼 증가하는 것을 의미 하는 것이 아니고
포인터가 가리키는 "자료형 의 단위 1" 만큼 증가된다.
-----------------------------------------------------
즉 ++p 인 경우에는 sizeof(자료형) 만큼 증가 됨을 의미합니다. char, int,
long의 경우 ++p의 의미는 다음과 같다.
전부 100번지 부터 시작 한다면
-----------------------------------------------
선언 연산 의미
-----------------------------------------------
char *p p++; 1 번지 증가 (101호로)
int *p p++; 2 번지 증가 (102호로)
long *p p++; 4 번지 증가 (104호로)
굳이 설명이 필요 없을 것 같고,예를 들어 char 에서는
main()
{
char rambo[3], *p;
p = rambo;
printf("%p", p); <-- 100 호 라고 치자
printf("%p", ++p); <-- 101호
}
Int 형에서는,
main()
{
int yong8[3], *pp;
pp = yong8;
printf("%p", pp); <-- 200 호 라고 치자
printf("%p", ++pp); <-- 202호
}
위에서 "용팔"이를 가리키는 포인터 pp가 왜 2 바이트씩 뛰었는지는 아실 것
입니다. 이 포인터는 int 타입을 가리키기로 했으므로, "다음집"으로 가려면
2 바이트(int 크기 ) 만큼 뛰어야 되는 것입니다.
이런 내용은 그림으로 명확히 이해 하는게 더 좋은 방법입니다. [181쪽]에
나오는 "포인터의 증가"의 그림 부분을 보세요.
<수정> [181쪽] [보기 3]의 그림에서 화살표는 "apt[2]"의 집을 가리켜야
합니다.
포인터에는 다음과 같이 4개의 연산자만 사용할 수 있습니다.
1. + -> p = p + 2;
2. - -> p = p - 2;
3. ++ -> p++; ++p;
4. -- -> p-- --p;
포인터 끼리의 덧셈은 의미가 없습니다. 예를들어 int *p1, *p2가 각각 100
200 번지를 갖고 있다고 치면, 그걸 더하면 300 인데 그게 누구네 집이란 말
인가 ? 아무의미가 없습니다.
포인터 끼리의 뺄셈은 같은 배열을 가리키고 있을 때만 의미가 있습니다.즉
main()
{
int rambo[5], *p1,*p2;
p1 = &rambo[0] --> 100 번지 라고 하자
p2 = &rambo[3] --> 106 번지 라고 하자
printf(" %d ", p2 - p1) --> 답 3 임.
}
<문> 왜 답이 6 이 아닐까 ?
<문> 다음을 실행해 보세요
main()
{
char *str="Good morning !";
*str='S';
printf("\n str => %s", str);
*str="Happy New Year";
printf("\n str => %s", str);
}
------------------------------
<문> 다음을 실행해 보세요
main()
{
char munja[]="ABCDEFG";
int suja[5], i=0;
while ( munja[i] != 0 )
printf(" %c ", munja[i++]);
for (i=0 ; i<5 ; i++)
suja[i] = i;
printf("\n\n");
for (i=0 ; i<8 ; i++)
printf(" %d ", suja[i]);
printf("\n\n munja => %p", munja);
printf(" \n sizeof(munja) => %d", sizeof(munja));
printf(" \n sizeof(suja) => %d", sizeof(suja));
}
------------------------------
<문> 다음을 실행해 보세요
main()
{
int a[3][2] = { {1,2}, {3,4}, {5,6} };
int i, j;
printf("\n a => %p\n", a);
for (i=0 ; i<3 ; i++) {
printf("\n *a + %d => %p", i, *a+i);
for (j=0 ; j<2 ; j++)
printf(" *(*(a+%d)+%d) : %d", i, j, *(*(a+i)+j) );
}
}
------------------------------
<문> 다음을 실행해 보세요
main()
{
int a[]={1,2,3}, i;
for (i=0 ; i<3 ; i++)
printf(" a[%d] => %d", i, a[i]);
printf("\n\n");
for (i=0 ; i<3 ; i++)
printf(" %d[a] => %d", i, i[a]); /* <--- Look ! */
}
************************< 끝 마치며 >**********************************
수고 하셨습니다.
***********************************************************************