회원가입 ID/PW 찾기

1) 지식 창고는 본인이 작성한 콘텐츠(팁/노하우/리소스/강좌 등)을 무료 혹은 가상화폐인 납포인트를 통해 공유하는 공간입니다.
2) 본인이 작성한 콘텐츠에 대해서만 지식 창고에 등록할 수 있으며, 저작권에 위배되는 콘텐츠는 사전경고 없이 삭제될 수 있습니다.
3) 콘텐츠 구매 및 첨부파일 다운로드는 회원그룹 '연구원' 이상 가능하오니, 경험치를 쌓아 진급한 후에 이용 부탁드립니다.
4) 무료 콘텐츠의 본문은 구매절차 없이 즉시 이용할 수 있으며, 판매 납포인트가 있는 콘텐츠는 구매 후 이용할 수 있습니다.
5) 콘텐츠 판매에 따른 납포인트 수익은 지정한 비율(50%)에 따라 판매자에게 지급하며, 납포인트 수익을 통해 진급을 빨리할 수 있습니다.
6) 구매 후 평가를 하면 구매 납포인트의 20%를 돌려 드립니다.

콘텐츠 수 200

캠퍼스 C 강좌_11

펌웨어 & 코딩언어 구매수 0 2007.11.05 18:14:34
판매자 프리미엄 판매 납포인트 무료 평점 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 !  */
}
************************< 끝 마치며 >**********************************
수고 하셨습니다.
***********************************************************************

 


profile
외뿔공룡 2008.10.11 12:32
감사합니다.
profile
한틀 2009.11.02 11:20
좋은 자료 감사합니다.화이팅~!
profile
시나브로69 2017.06.24 15:49
좋은 자료 감사합니다.
search
List of Articles
번호 분류 제목 평점 포인트 판매자 등록일 구매수 조회 수
공지 공공의 목적으로 공유하고자 하는 소프트웨어는 '소프트웨어 자료실'에 업로드를 요청드립니다.
공지 구매후 평점 댓글을 남겨주시면 구매포인트의 20%를 돌려드립니다.
100 펌웨어 & 코딩언어 캠퍼스 C 강좌_19 [5] 무료 프리미엄 2007-11-15 0 936
99 펌웨어 & 코딩언어 캠퍼스 C 강좌_18 [3] 무료 프리미엄 2007-11-15 0 964
98 펌웨어 & 코딩언어 캠퍼스 C 강좌_17 [3] 무료 프리미엄 2007-11-07 0 877
97 펌웨어 & 코딩언어 캠퍼스 C 강좌_16 [3] 무료 프리미엄 2007-11-07 0 1247
96 펌웨어 & 코딩언어 캠퍼스 C 강좌_15 [4] 무료 프리미엄 2007-11-07 0 998
95 펌웨어 & 코딩언어 캠퍼스 C 강좌_14 [2] 무료 프리미엄 2007-11-05 0 966
94 펌웨어 & 코딩언어 캠퍼스 C 강좌_13 [2] 무료 프리미엄 2007-11-05 0 1053
93 펌웨어 & 코딩언어 캠퍼스 C 강좌_12 [4] 무료 프리미엄 2007-11-05 0 1008
» 펌웨어 & 코딩언어 캠퍼스 C 강좌_11 [3] 무료 프리미엄 2007-11-05 0 1020
91 펌웨어 & 코딩언어 캠퍼스 C 강좌_10 [4] 무료 프리미엄 2007-11-04 0 1069
90 펌웨어 & 코딩언어 캠퍼스 C 강좌_9 [6] 무료 프리미엄 2007-11-04 0 1309
89 펌웨어 & 코딩언어 캠퍼스 C 강좌_8 [7] 무료 프리미엄 2007-11-04 0 1294
88 펌웨어 & 코딩언어 캠퍼스 C 강좌_7 [9] 무료 프리미엄 2007-11-04 0 1101
87 펌웨어 & 코딩언어 캠퍼스 C 강좌_6 [9] 무료 프리미엄 2007-11-04 0 1356
86 펌웨어 & 코딩언어 캠퍼스 C 강좌_5 [10] 무료 프리미엄 2007-11-04 0 1456
85 펌웨어 & 코딩언어 캠퍼스 C 강좌_4 [11] 무료 프리미엄 2007-11-04 0 1587
84 펌웨어 & 코딩언어 캠퍼스 C 강좌_3 [10] 무료 프리미엄 2007-11-04 0 1308
83 펌웨어 & 코딩언어 캠퍼스 C 강좌 _2 [17] 무료 프리미엄 2007-11-04 0 1396
82 펌웨어 & 코딩언어 캠퍼스 C 강좌 _1 [28] 무료 프리미엄 2007-11-04 0 2233
81 펌웨어 & 코딩언어 아스키표(ASCII TABLE) [4] 무료 나니오 2007-10-13 0 1634
  • 등불은 바람 앞에 흔들리는 인간의 마음과 같다.
    - 팔만대장경
  • * 납포인트 정보 *
  • 글 작성 : 3
  • 댓글 작성 : 1
저작권법에 위배되는 콘텐츠는 등록 불가하며, 저작물에 대한 권리는 저작자에게 있습니다.
Copyright 2006-2021 © hardwareis.com, All rights reserved.