[질문] 소스의 이해 ^^

naisr00t의 이미지


typedef unsigned char     M_Uint8;
typedef unsigned short    M_Uint16;
typedef unsigned int      M_Uint32;
typedef char     M_Int8;
typedef short    M_Int16;
typedef int      M_Int32;


#define READ16(ptr, pos)	(M_Int16)(*((M_Uint8*)ptr+pos) | (*((M_Uint8*)ptr+pos+1) << 8))
#define READ32(ptr, pos)	(M_Int32)(*((M_Uint8*)ptr+pos) | (*((M_Uint8*)ptr+pos+1) << 8) | (*((M_Uint8*)ptr+pos+2) << 16) | (*((M_Uint8*)ptr+pos+3) << 24))


int JarFile_getJarInfo(int fd, char* name, int* offset, int* compressed_size, int* uncompressd_size, int* compress_meth)
{
    char buf[22];
    char fileName[256];
    char* cBuf;
    int cDirSize, cDirOff, entryCount;
    int i , res, fnLen ;
    
    if ( lseek(fd, -22, SEEK_END) < 0 ) {
        return(-1);
    }

    read(fd, buf, 22);

    if (READ32(buf, 0) != 0x06054b50 ) {
        return(-1);
    }

    ...
    ...
    ... 

    for ( i = 0; i < entryCount ; i++ ) {
        *compress_meth = READ16(cBuf, 10);
        *compressed_size = READ32(cBuf, 20);
        *uncompressd_size = READ32(cBuf, 24);
    ...
    ...
    ...
    }

     ...
     ...
}

위의 코드가 있을 때, 이해가 도저히 안가는 부분이
READ16, READ32 함수를 부를 때 입니다. 어떻게 연산이 되는지 알려주시면 고맙겠습니다.

sodomau의 이미지

READ16과 READ32의 매크로 정의 부분을 보시면
됩니다.

간단히 READ16만 보면

#define READ16(ptr, pos)   (M_Int16)(*((M_Uint8*)ptr+pos) | (*((M_Uint8*)ptr+pos+1) << 8)) 

여기서 보면 ptr 포인터에서부터 pos번째 바이트와 그 다음 번째 바이트를 16 shift시킨 값을 | (or) operator로 16비트짜리 숫자로 합쳐버리는 작용을 하네요.

(M_Int16) (ptr+pos 위치의 바이트) | (ptr+pos+1 번째 바이트<<8)

코드는 리틀엔디안 기준이군요.

dyks의 이미지

sodomau wrote:
코드는 리틀엔디안 기준이군요.

리틀 엔디안 기준은 아니지 않나요?
빅 엔디안 <-> 리틀 엔디안 으로 바꾸는 매크로 같은데요.

원래 스트림이 빅 엔디안이면 리틀 엔디안으로, 반대의 경우엔 역시 반대로 바꾸는 매크로 아닌가요?

newmania의 이미지

endian 문제를 극복할 수 있도록 만들어둔 매크로라고 생각할 수 있겠네요.

sodomau의 이미지

C 코딩을 해 본지 하도 오래되어서-_-
테스트 함 해 봤습니다 -_-;;

$ cat test2.c
#include<stdio.h>

char buff[]={0x1,0x7f};
void main()
{
        printf("%d\n",*(short *)buff);
        printf("%d\n",(short)(buff[0] | buff[1]<<8));
}

sodomau@somakido ~
$ ./test2
32513
32513

little endian 기준이 맞습니다;

수정;;;;

어제밤에 하도 정신이 없어서;;

리틀 엔디안 기준이 아니라...
버퍼에 담겨있는 스트림만 리틀 엔디안이고
코드 자체는 빅엔디안이나 리틀 엔디안에서 모두 동일한 결과를
갖도록 사용가능하게 되어 있네요;

음;; 코딩 해 본지 정말 오래된 것 같은...;;