블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아
    동화다아아

    카테고리

    분류 전체보기 (176)
    잡담 (1)
    IT 기기-리뷰&뉴스 (7)
    리뷰 - 도서 (1)
    리뷰 - 영상 (0)
    리뷰 - 그림/음악 (1)
    내장형 하드웨어 (163)
    Total
    Today
    Yesterday

    - 함수 포인터

    ⇒ 변수나 파일을 포인터 변수를 이용하여 접근하듯이, 함수도 포인터를 이용하여 호출할 수 있다. 함수 포인터(function pointer)는 함수의 실행코드의 시작주소를 가지고 있으며, 함수 포인터를 이용하여 함수를 호출할 수 있다. 배열 이름이 메모리 주소값을 가지는 상수이듯이, 함수 이름도 함수의 시작코드의 주소값을 가지는 주소값 상수로 볼 수 있다.

    ⇒ 반환자료형 (* 함수 포인터 변수 이름) (인수1, 인수2, ……, 인수 n);


    // 함수 포인터 예제
    #include<stdio.h>
    int(*test(void)) (const char *, ...);
    int(*(*test2(void))(void)) (const char *, ...);
    int main()
    {
            
    int (*fp) (const char *, ...)=0// printf를 가리키는 함수 포인터
                                      // 포인터 변수 fp을 0으로 초기화 했다.
            
    fp = printf;
            fp(
    "Hi!!!\n");
      
            
    return 0;
    }
    int(*test(void)) (const char *, ...)
    {
            
    return printf;
    }
    int(*(*test2(void))(void)) (const char *, ...)
    {
            
    return test;
    }

    ⇒ main() 안에서 int (*fp)(const char *, ...) = 0; 가 선언되었다. 이것은 printf를 가리키는 함수 포인터이다.

    int(*test(void)) (const char *, ...) 함수를 살펴보면

     → printf의 원형 int (*) (const char *, ...)에서 (* 다음에 test(void)를 삽입한 모습임을 알 수 있다.

    ⇒ test와 test2 함수는 위 소스에서 출력과는 관계가 없다.




    // 인자를 가진 함수 포인터 문제 풀이

    #include <stdio.h>

    //int printf(const char *, ...); printf를 반환한다는뜻
    //test1(float f);
    int(*test1(float f))(const char *, ...);

    //test2(char c);
    int (*(*test2(char))(float))(const char *, ...)

    int main()
    {
            
    int (*fp)(const char *, ...)=0;
            
    //int printf(const char *, ...);

            //fp1 선언
            
    int (*(*fp1)(float f))(const char *, ...)=0// 포인트가 1개, 함수 선언이 아니다.

            //fp2 선언
            
    int (*(*(*fp2)(char c))(float))(const char *, ...)=0

                                    // 포인트가 1개(3개가 아니다.), 함수 선언이 아니다.
            
    fp2 = test2;
            fp1 
    = fp2('a');
            fp  
    = fp1(0.1);

            fp(
    "Hi....\n");
            
    return 0;
    }

    int (*test1(float f))(const char *, ...)
    {
            printf(
    "float : %0.1f\n", f);
            
    return printf;
    }

    int (*(*test2(char c))(float))(const char *, ...)
    {
            printf(
    "char : %c\n", c);
            
    return test1;
    }

    ⇒ test1 함수 선언

     → int printf(const char *, ...);

     → int (*)(const char *, ...);

     → int (* 까지 test1 앞에 복사

     → int (*test1(float f) 다음에 나머지 )(const char *, ...);를 붙여 넣는다.


    ⇒ fp1 선언

     → int (*test1(float f))(const char *, ...);를 fp1으로 선언하기 위해 붙여넣고.

     → int (*fp)(const char *, ...)=0;와 int printf(const char *, ...); 를 비교해 보면 printf가 (*fp)로 바뀌었음을 알 수 있다.

     → 따라서 int (*test1(float f))(const char *, ...)를 같게 하면

     → int (*(*fp1)(float f))(const char *, ...)=0; 으로 바꾸어 진다.


    ⇒ test2 함수 선언

     → test1의 타입이 필요하므로 복사 - int (*test1(float f))(const char *, ...)

     → test1을 (*)로 변경 - int (*(*)(float f))(const char *, ...)

     → int (*(* 까지 test2 앞에 복사

     → int (*(*(test2(char c) 다음에 나머지 )(float f))(const char *, ...)를 붙여넣는다.

     → int (*(*(test2(char c))(float))(const char *, ...);가 된다.


    ⇒ fp2 선언

     → int (*(*(test2(char c))(float))(const char *, ...);를 fp2로 선언하기 위해 붙여넣고.

     → fp1과 같이 int (*(*fp1))(const char *, ...)=0;와 int printf(const char *, ...); 를 비교하면 (*(*(fp2)))가 된다.

     → 따라서 int (*(*(*fp2)(char c))(float))(const char *, ...)=0; 으로 바꾸어진다.



    - 다중 포인터 개념

    int A = 100;

    int *P = &A;

    int **PP = &P;

    int ***PPP = &PP;

     

    ⇒ 정리해보면 아래 표와 같다.

     

    *

    **

    ***

    A → 100(값)

    *A → error

    **A → error

    ***A → error

    P → 1000(주소)

    *P → 100(값)

    **P → error

    ***P → error

    PP → 2000(주소)

    *PP → 1000(주소)

    **PP → 100(값)

    ***PP → error

    PPP → 3000(주소)

    *PPP → 2000(주소)

    **PPP → 1000(주소)

    ***PPP → 100(값)



    // 다중 포인터 예제
    #include<stdio.h>
    int main()
    {
            
    int A = 100;
            
    int *P = &A;
            
    int **PP = &P;
            
    int ***PPP = &PP;

            printf(
    "------------------\n");
            printf(
    "&A   : %08X\n"&A);
            printf(
    "&P   : %08X\n"&P);
            printf(
    "&PP  : %08X\n"&PP);
            printf(
    "&PPP : %08X\n"&PPP);

            printf(
    "------------------\n");
            printf(
    "A    : %d\n", A);
            printf(
    "P    : %08X\n", P);
            printf(
    "PP   : %08X\n", PP);
            printf(
    "PPP  : %08X\n", PPP);
     
            printf(
    "------------------\n");
            
    //printf("*A    : %d\n", *A); 
           //error - 곱셈기호 '*' 로 해석된다.
            
    printf("*P    : %d\n", *P);
            printf(
    "*PP   : %08X\n", *PP);
            printf(
    "*PPP  : %08X\n", *PPP);
      
            printf(
    "------------------\n");
            
    //printf("**A    : %d\n", **A); - error
            //printf("**P    : %08X\n", **P); - error
            
    printf("**PP   : %d\n", **PP);
            printf(
    "**PPP  : %08X\n", **PPP);
      
            printf(
    "------------------\n");
            
    //printf("***A    : %d\n", ***A); - error
            //printf("***P    : %08X\n", ***P); - error
            //printf("***PP   : %08X\n", ***PP); - error
            
    printf("***PPP  : %d\n", ***PPP);
      
            
    return 0;
    }

    ⇒ 출력 결과         

     



    - 구조체
    #include<stdio.h>
    typedef struct
    {
            
    int A;
            
    int B;
            
    int C;
    }EMB;
    int main()
    {
            
    int array[6];
            EMB *stp;
            
    unsigned char *UCP;
            stp 
    = (EMB *)array;
            UCP 
    = (unsigned char *)array;
      
            *UCP 
    = 0x64;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
      
            ++UCP;
            *UCP 
    = 0x63;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
      
            ++UCP;
            *UCP 
    = 0x62;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
      
            ++UCP;
            *UCP 
    = 0x61;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
            ++UCP;
            *UCP 
    = 0x00;
      
            printf(
    "===========================\n");
            printf(
    "stp -> A : %d\n", stp -> A);  
            printf(
    "stp -> B : %d\n", stp -> B);  
            printf(
    "stp -> C : %d\n", stp -> C);  

            printf(
    "==========================\n");
            printf(
    "array[0] : %d\n", array[0]);  
            printf(
    "array[1] : %d\n", array[1]);  
            printf(
    "array[2] : %d\n", array[2]);  

            printf(
    "===========================\n");
            stp 
    = (EMB *)&array[1];
      
            printf(
    "stp -> A : %d\n", stp -> A);  
            printf(
    "stp -> B : %d\n", stp -> B);  
            printf(
    "stp -> C : %d\n", stp -> C);  

            printf(
    "===========================\n");
            UCP 
    = (unsigned char *)array;
            ++UCP;
            stp 
    = (EMB *)UCP;

            printf(
    "stp -> A : %d\n", stp -> A);  
            printf(
    "stp -> B : %d\n", stp -> B);  
            printf(
    "stp -> C : %d\n", stp -> C);  

            
    return 0;
    }

    ⇒ 출력 결과         

     

    ⇒ 메모리 모양 예상

    64

    00

    00

    00

    63

    00

    00

    00

    62

    00

    00

    00

    61

    00

    00

    00

    ⇒ 출력 결과를 통해 stp -> A부터 C까지와 array[0]부터 array[2]까지는 같은 값을 가지는 것을 알 수 있다.

    64

    00

    00

    00

    63

    00

    00

    00

    62

    00

    00

    00

    61

    00

    00

    00

    ⇒ 출력 결과(%08X)         

       

    ⇒ *UCP = 0x64; 를 통해 int array[6]에 1바이트씩 값을 넣고 있는데 처음에는 64 00 00 00 의 순서로 값이 들어간 것을 확인할 수 있다. 단, CPU가 little endian방식을 취하므로 들어가는 것과 출력이 다르다. (%d로 출력하면 100, 99, 98이 출력된다.)

    ⇒ 세 번째 출력의 stp -> A부터 C까지를 확인해 보면

            stp = (EMB *)&array[1];

       를 통해 A가 array[1]에서 시작되어 C가 array[3]까지 표시된다.

    64

    00

    00

    00

    63

    00

    00

    00

    62

    00

    00

    00

    61

    00

    00

    00

     → %d로 출력하면 98, 97, 96이 출력된다.

    ⇒ 출력 결과(%08X)        

          UCP = (unsigned char *)array;

            ++UCP;

            stp = (EMB *)UCP;

     → 위의 소스로 1바이트만큼 이동한 UCP가 stp에 대입되고 따라서 stp가 가리키는 값은

    64

    00

    00

    00

    63

    00

    00

    00

    62

    00

    00

    00

    61

    00

    00

    00

    가 된다.

    ⇒ 출력 결과(%08X)         

     

    → %d로 출력         

     


    Posted by 동화다아아
    , |

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함