끄적끄적

반응형

포인터는 이해하는 것이 중요한 것이지 외우는 것이 중요하지는 않습니다.

저 같은 경우는 자주 사용하는 포인터는 항상 머리속에 있지만 그렇지 않은 포인터들은 이렇게 정리해 놓고 보고 쓰곤 합니다.

여러분들도 그렇게 하는 것이 좋지 않을까 생각합니다.

 

#include <stdio.h>

#include <string.h>

#include <malloc.h>

#include <stdlib.h>

#include <conio.h>

#pragma warning(disable:4101)   // C4101 경고 에러 제거

void main( void )

{

    /* 기본 포인터 int*/

    {

    int  i;

    int* pi1;    // 선언 방법 1 (권장)

    int *pi2;    // 선언 방법 2   

    int * pi3;   // 선언 방법 3

    pi2 = &i;    // i의 번지값을 대입

    // 변수에 값을 대입 (세 문장은 모두 동일)

    i      = 5;    // 직접 대입

    *pi2   = 5;  // pi2 변수의 값(i의 번지)의 번지에 간접 접근해서 대입

    pi2[0] = 5;  // pi2 변수의 0번째 배열 요소에 접근해서 대입

    }

    //*/

    //.// 일반 변수의 크기 (각 데이터형이 차지하는 메모리 크기)

    printf( "%d \n", sizeof(char) );    // 1 바이트

    printf( "%d \n", sizeof(int) );       // 4 바이트

    printf( "%d \n", sizeof(long) );    // 4 바이트

    printf( "%d \n", sizeof(float) );    // 4 바이트

    printf( "%d \n", sizeof(double) );  // 8 바이트

    //.// 포인터 변수의 크기 (번지값을 저장하기 위한 변수이므로 모두 4)

    printf( "%d \n", sizeof(char*) );   // 4 바이트

    printf( "%d \n", sizeof(int*)  );     // 4 바이트

    printf( "%d \n", sizeof(long*)  );  // 4 바이트

    printf( "%d \n", sizeof(float*) );   // 4 바이트

    printf( "%d \n", sizeof(double*) ); // 4 바이트

    /* 문자형 포인터 char*/

    {

    char  ch;

    char* pch;

    pch = &ch;

    ch     = 'a';     // 변수에 값을 대입 (세 문장은 모두 동일)

    *pch   = 'a';    // pi 변수의 값(i의 번지)의 번지에 간접 접근해서 대입

    pch[0] = 'a';   // pi 변수의 0번째 배열 요소에 접근해서 대입

    }

    //*/

    /* 문자열형 포인터 char*/

    {

    char string[10] = "winter";

    char* pstr;

    pstr = string;         // 선두 번지 상수 값

    pstr = &string[0];  // 0번째 요소의 번지 값

    

    *pstr     = 'W';     // 첫 번째 요소에 'W'를 대입

    pstr[0]   = 'W';    // 첫 번째 요소에 'W'를 대입

    *(pstr+0) = 'W';    // 첫 번째 요소에 'W'를 대입

    

    pstr[1]   = 'I';    // 두 번째 요소에 'I'를 대입

    *(pstr+1) = 'I';    // 두 번째 요소에 'I'를 대입

    

    pstr++;             // 1번지 만큼 증가, ++pstr도 동일

    *pstr     = 'I';    // 두 번째 요소에 'I'를 대입

    pstr[0]   = 'I';    // 두 번째 요소에 'I'를 대입, pstr이 1증가했기 때문

    *(pstr+0) = 'I';    // 두 번째 요소에 'I'를 대입

    pstr--;              // 1번지 만큼 감소, --pstr도 동일

    strcpy( string    , "summer" );      // string과 pstr은 같은 번지 값

    strcpy( &string[0], "summer" );   // string과 &string[0]은 같은 번지 값

    strcpy( pstr      , "summer" );      // strcpy는 같은 번지를 넘겨 받음

    strcpy( string+2  , "summer" );    // string+2는 &string[2]와 동일

    strcpy( &string[2], "summer" );   // 

    strcpy( pstr+2    , "summer" );     // 

    }

    //*/

    /* 문자열형 포인터 char*의 잘못된 사용 */

    {

    char* pstr = "winter";  // pstr은 상수 영역 포인터

    char* ptmp;               // 임시 포인터

    *pstr     = 'W';      // 상수 영역을 읽기만 가능, 프로그램 다운

    pstr[0]   = 'W';     // 상수 영역을 읽기만 가능, 프로그램 다운

    *(pstr+0) = 'W';    // 상수 영역을 읽기만 가능, 프로그램 다운

    ptmp = pstr;         // pstr 값과 일치 시킴

    *ptmp     = 'W';    // pstr과 같은 번지 값을 갖기 때문에 프로그램 다운

    ptmp[0]   = 'W';   // pstr과 같은 번지 값을 갖기 때문에 프로그램 다운

    *(ptmp+0) = 'W';  // pstr과 같은 번지 값을 갖기 때문에 프로그램 다운

    printf( "%c", *pstr );     // w가 출력, 읽기는 가능

    printf( "%c", pstr[0] );  // w가 출력, 읽기는 가능

    

    pstr++;

    printf( "%c", *pstr );    // i가 출력, 읽기는 가능

    printf( "%c", pstr[0] );  // i가 출력, pstr++로 pstr의 시작 번지가 1증가됨

    pstr--;

    strcpy( pstr, "summer" ); // 상수 영역에 summer 복사 불가능

    strcpy( ptmp, "summer" ); // pstr == ptmp 이므로 불가능

    printf( pstr );   // winter가 출력, 읽기는 가능

    printf( ptmp );   // winter가 출력, 일기는 가능

    }

    //*/

    /* 1차원 정수형 배열의 포인터 int*

    {

    int array[5] = { 1, 2, 3, 4, 5 };

    int* p;

    

    p = array;      // 배열의 선두 번지

    p = &array[0];  // 배열의 선두 번지

    p = array + 1;  // 배열의 두 번째 번지

    p = &array[1];  // 배열의 두 번째 번지

    p = array;

    *p     = 100;   // 현재 p가 가리키는 요소에 100을 대입

    p[0]   = 100;   // 현재 p가 가리키는 0번째 요소에 100을 대입

    *(p+0) = 100;   // 현재 p가 가리키는 0번째 요소에 100을 대입

    p++;            // int형 데이터 배열이므로 4가 증가 (중요)

    p = p + 1;      // p++과 동일, 4가 증가

    p = p + 2;      // 8이 증가, (sizeof(int) * 2) == 8

    }

    //*/

    /* 2차원 정수형 배열의 포인터 int (*)[]

    {

    int array[2][3] = { 1, 2, 3, 4, 5, 6 };

    int (*p)[3];

    int **p2;

    

    p = array;      // 배열의 선두 번지, int (*)[3]

    p = &array[0];  // 배열의 선두 번지

    printf( "%#x \n", p[1]        ); // 0x12ff34

    printf( "%#x \n", p+1         ); // 0x12ff34

    printf( "%#x \n", *(p+1)      ); // 0x12ff34

    printf( "%d  \n", **(p+1)     ); // 4

    printf( "%d  \n", *(*(p+1))   ); // 4

    printf( "%d  \n", *(*(p+1)+0) ); // 4

    printf( "%d  \n", *(*(p+1)+1) ); // 5

    printf( "%d  \n", *(*(p+1)+2) ); // 6

    //p = &array[0][0]; - 틀림, &array[0][0]은 int *

    //p = array[0];     - 틀림, array [0]   은 int *

    //p = array [0][0]; - 틀림, array [0][0]은 int

    p = array + 1;  // 배열의 두 번째 번지

    p = &array[1];  // 배열의 두 번째 번지

    p = array;

    p[0][0] = 100;     // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입

    *(*(p+0)+0) = 100; // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입

    p[1][2] = 200;     // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입

    *(*(p+1)+2) = 200; // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입

    p++;            // int(*)[3]형 배열이므로 12가 증가 sizeof(int) * 3

    p = p + 1;      // p++과 동일, 12가 증가

    p = p + 2;      // 24가 증가, (sizeof(int) * 3 * 2)

    }

    //*/

    /* 2차원 배열을 int *로 사용

    {

    int array[2][3] = { 1, 2, 3, 4, 5, 6 };

    int *p;

    int i;

    

    p = array[0];   // 배열의 선두 번지, int *

    for( i=0; i<sizeof(array)/sizeof(int)/2; i++ )

    {

        printf( "%d \n", *p++ );

    }

    //p = &array[0];  - 틀림 int (*)[3]

    p = &array[0][0];   // 첫 번째 배열의 주소

    p = &array[0][1];   // 두 번째 배열의 주소

    p = &array[1][0];   // 네 번째 배열의 주소

    printf( "%d  \n", p[0]   ); // 4

    printf( "%#x \n", p+0    ); // 0x12ff14

    printf( "%d  \n", *(p+0) ); // 4

    printf( "%d  \n", *(p+1) ); // 5

    printf( "%d  \n", *(p+2) ); // 6

    p = array[0];   // 배열의 선두 번지, int *

    p[0]   = 100;  // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입

    *(p+0) = 100;  // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입

    p[1]   = 200;  // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입

    *(p+1) = 200;  // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입

    p++;            // int*형이므로 4만 증가

    p = p + 1;      // p++과 동일, 4가 증가

    p = p + 2;      // 8이 증가, sizeof(int) * 2

    }

    //*/

    /* 3차원 정수형 배열의 포인터 int (*)[][]

    {

    int array[2][3][4] = 

    { 

        { { 1,  2,  3,  4}, { 5,  6,  7,  8}, { 9, 10, 11, 12} },

        { {13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24} } 

    };

    int (*p)[3][4];

    int ***p2;

    

    p = array;      // 배열의 선두 번지, int (*)[3][4]

    p = &array[0];  // 배열의 선두 번지

    printf( "%#x \n", p[0]        ); // 0x12fea0

    printf( "%#x \n", p+0         ); // 0x12fea0

    printf( "%#x \n", p+1         ); // 0x12fed0 <-

    printf( "%#x \n", *(p+0)      ); // 0x12fea0

    printf( "%#x \n", **(p+0)     ); // 0x12fea0

    printf( "%d  \n", ***(p+0)    ); // 1

    printf( "%#x \n", *(*(p+0))   ); // 0x12fea0

    printf( "%#x \n", *(*(p+0)+0) ); // 0x12fea0

    printf( "%#x \n", *(*(p+0)+1) ); // 0x12feb0 <-

    printf( "%#x \n", *(*(p+0)+2) ); // 0x12fec0 <-

    

    printf( "%d  \n", *(*(*(p+0)+0)+0)  ); //  1  , p[0][0][0] == [0]

    printf( "%d  \n", *(*(*(p+0)+0)+1)  ); //  2  , p[0][0][1] == [1]

    printf( "%d  \n", *(*(*(p+0)+0)+2)  ); //  3  , p[0][0][2] == [2]

    printf( "%d  \n", *(*(*(p+0)+0)+3)  ); //  4  , p[0][0][3] == [3]

    printf( "%d  \n", *(*(*(p+0)+1)+0)  ); //  5  , p[0][1][0] == [4]

    printf( "%d  \n", *(*(*(p+0)+1)+1)  ); //  6  , p[0][1][1] == [5]

    printf( "%d  \n", *(*(*(p+0)+1)+2)  ); //  7  , p[0][1][2] == [6]

    printf( "%d  \n", *(*(*(p+0)+1)+3)  ); //  8  , p[0][1][2] == [7]

    printf( "%d  \n", *(*(*(p+1)+2)+0)  ); // 21  , p[1][2][0] == [20]

    printf( "%d  \n", *(*(*(p+1)+2)+1)  ); // 22  , p[1][2][1] == [21]

    printf( "%d  \n", *(*(*(p+1)+2)+2)  ); // 23  , p[1][2][2] == [22]

    printf( "%d  \n", *(*(*(p+1)+2)+3)  ); // 23  , p[1][2][3] == [23]

    p++;            // 48이 증가 sizeof(int) * 3 * 4

    p = p + 1;      // p++과 동일, 48이 증가

    p = p + 2;      // 96이 증가, sizeof(int) * 3 * 4 * 2

    }

    //*/

    /* 구조체 포인터

    {

    struct Jusorok

    {

        int data;

        char name[20];

        int  *p;

        struct Jusorok* next;

    };

    

    struct Jusorok  J;

    struct Jusorok* PJ;

    //PJ = J;     // 타입 불일치 에러

    PJ = &J;      // 올바른 표현

    J.data = 5;

    strcpy( J.name, "이상미" );

    

    J.p = (int*) malloc( 500 );

    J.next = NULL;

    printf( "%d \n", J.data );    // pJ->data 와 동일

    printf( "%d \n", PJ->data );  // J.data와 동일

    }

    //*/

    /* 링크드 리스트

    {

    typedef struct tagList

    {

        int data;

        struct tagList* next;

    } LIST, *PLIST;

    

    PLIST p;

    PLIST Head, Tail;

    p = (PLIST) malloc( sizeof(LIST) );

    memset( p, 0, sizeof(LIST) );

    p->data = 1;

    Head = Tail = p;

    printf( "%#x \n", &p );         // 0x12fe70

    printf( "%#x \n", p  );         // 0x3733e0

    printf( "%#x \n", &p->data );   // 0x3733e0

    printf( "%d  \n", p->data  );   // 1

    printf( "%#x \n", &p->next );   // 0x3733e4

    printf( "%#x \n", p->next  );   // 0

    p = (PLIST) malloc( sizeof(LIST) );

    memset( p, 0, sizeof(LIST) );

    p->data = 2;

    Tail->next = p;

    Tail = p;

    printf( "%#x \n", &p );         // 0x12fe70

    printf( "%#x \n", p  );         // 0x373418

    printf( "%#x \n", &p->data );   // 0x373418

    printf( "%d  \n", p->data  );   // 2

    printf( "%#x \n", &p->next );   // 0x37341c

    printf( "%#x \n", p->next  );   // 0

    p = Head;

    while( p )

    {

        printf( "%d \n", p->data ); // 1, 2

        p = p->next;

    }

    }

    //*/

    /* 1차원 구조체 배열

    {

    typedef struct

    {

        int data;

    } ARRAY;

    

    ARRAY array[10];

    ARRAY *p;

    int i;

    for( i=0; i<sizeof(array)/sizeof(ARRAY); i++ )

    {

        array[i].data = i;

    }

    p = array;

    for( i=0; i<sizeof(array)/sizeof(ARRAY); i++ )

    {

        printf( "%d \n", p[i].data );

        printf( "%d \n", (*(p+i)).data );

        printf( "%d \n", (p+i)->data );

    }

    }

    //*/

    /* 함수 포인터

    {

    int (*LEN) ( const char* );

    typedef int(*FLEN) ( const char* );


    FLEN l1, l2;

    FLEN f[3] = { strlen, strlen, strlen };

    LEN = strlen;

    l1 = l2 = strlen;

    printf( "%d \n", strlen ("12345") );    // 5

    printf( "%d \n", LEN    ("12345") );    // 5

    printf( "%d \n", l1     ("12345") );    // 5

    printf( "%d \n", l2     ("12345") );    // 5

    printf( "%d \n", f[0]   ("12345") );    // 5

    printf( "%d \n", (f[1]) ("12345") );    // 5

    printf( "%d \n", (*f[2])("12345") );    // 5

    }

    //*/

    /* 표현식

    {

        int number[] = {0,1,2,3,4,5,6,7,8,9};

        char *p;

        p = number;

        printf( "%d \n", *p++ );

        printf( "%d \n", *p-- );

        printf( "%d \n", *++p );

        printf( "%d \n", ++*p );

        printf( "%d \n", (*p)++ );

        printf( "%d \n", (*p)-- );

        printf( "%d \n", *(p+1) );

        printf( "%d \n", *(1+p) );

    }

    //*/

}



반응형
Please Enable JavaScript!
Mohon Aktifkan Javascript![ Enable JavaScript ]