함수포인터를 이용한 유용한 기법중 하나인 “메세지 기법”에 대하서 정리했다.

struct MFT_Entry_Attribute_Type
{
    unsigned short	usNum;
    const char *	cDes;
    void (*fp)(void *);
} MFT_Attr_Type[] = {
    { 16, "$STANDARD_INFORMATION", Content_STD_INFO}
    ,{ 32, "$ATTRIBUTE_LIST",0}
    ,{ 48, "$FILE_NAME",Content_FILE_NAME}
    ,{ 64, "$VOLUME_VERSION or $OBJECT_ID",0}
    ,{ 80, "$SECURITY_DESCRIPTOR",0}
    ,{ 96, "$VOLUME_NAME",0}
    ,{112, "$VOLUME_INFORMATION",0}
    ,{128, "$DATA",0}
    ,{144, "$INDEX_ROOT",0}
    ,{160, "$INDEX_ALLOCATION",0}
    ,{176, "$BITMAP",0}
    ,{192, "$SYMBOLICK_LINK or REPARSE_POINT",0}
    ,{208, "$EA_INFORMATION",0}
    ,{224, "$EA",0}
    ,{256, "$LOGGED_UTILITY_STREAM",0}
    ,{257, "Unknown",0}
};
MFT_Entry_Attribute_Type 구조체는
  • 직접적인 비교에 쓰일 변수 한 개와
  • 메세지 출력을 위한 const char * 형의 변수 한 개,
  • 필요에 따라 함수를 호출할 수 있도록 함수 포인터 선언

으로 이루어져 있으며 소스에서 보는 바와 같이 구조체 선언과 동시에 구조체 배열 변수를 선언해 두었다.


이것을 어떻게 사용하는지 아래 소스에서 살펴보면,

void * test(void *p)            /* 213 페이지 */
{
    struct MFT_Entry_Attribute_Type * stpAttType;

    printf("========================= MFT Entry Attribute Analysis =========================\n");
    printf("Attribute Type                   : ");
    stpAttType = MFT_Attr_Type;
    while(1)
    {
        if(257 == (stpAttType->usNum))
        {
            break;
        }
        else if ((*((U32*)((U8*)p+0))) == stpAttType->usNum) /* 이동은 U8만큼으로 하고 보는건 U32로 보겠다 */
        {
            break;
        }
        ++stpAttType;
    }
    printf("%s\n", stpAttType->cDes);
    printf("Lenth of Attribute               : %dBytes\n", *((U32*)((U8*)p+4))); /* 이 길이를 알아내면 #2의 위치를 알 수 있다. */
    printf("Non-Resident Attribute           : %s\n", 1==(*((U8*)p+8)) ? "Yes":"No");
    printf("Lenth of Name                    : %d\n", *((U8*)p+9));
    printf("Offset to Name                   : %d\n", *((U16*)((U8*)p+10)));
    printf("Attribute Flags                  : ");
    if ( 0 != (0x0001 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Compressed ");
    }
    if ( 0 != (0x4000 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Encrypted ");
    }
    if ( 0 != (0x8000 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Sparse ");
    }
    if ( 0 == (0xC001 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Nothing");
    }
    putchar('\n');
    printf("Attribute Identifier             : 0x%04X\n", *((U16*)((U8*)p+14)));

    if(0==(*((U8*)p+8)))	// Resident Attribute 
    {
        printf("=== Resident Attribute========================\n");
        printf("====== Size of Content           : %d\n", *((U32*)((U8*)p+16)));
        printf("====== Offset to Content         : %d\n", *((U16*)((U8*)p+20)));
        printf("====== Index Flag                : %s\n", 1==(*((U8*)p+22)) ? "Yes":"No");
        printf("====== Padding                   : 0x%02X\n", *((U8*)p+23)); /* Reserve ㅇ */
        printf("==============================================\n");
    }
    else					// Non-Resident Attribute 
    {
    }
	
    if(0!=(stpAttType->fp))     /* 호출 함수가 있다면 호출 한다. */
    {
        (stpAttType->fp)(    (U8*)p + (*((U8*)p+20))     ); /* 함수 포인터 */
    }
    return (U8*)p + (*((U32*)((U8*)p+4))) ;
}
  • 3번 줄에서 위에서 선언한 MFT_Entry_Attribute_Type * stpAttType 포인터 변수 선언
  • 7번에서 전역으로 선언된 MFT_Attr_Type을 stpAttType에 대입
  • 8번줄에서 무한 루프를 돌면서 해당하는 값이 있는지 찾고 없으면 다음 값으로
  • 20번줄에서 해당 메세지를 출력
  • 58번줄에서 함수포인터 사용여부를 검사하여 호출 또는 넘어간다.

위와 같은 기법을 이용하면 메뉴 호출또는 메세지등을 손쉽게 할 수 있다.


저작자 표시
신고

'컴퓨터 언어 > C' 카테고리의 다른 글

pThread를 이용한 Thread  (0) 2013.03.05
Static 변수  (0) 2013.02.25
메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10