8bit 포인터에서 16 bit 값 읽어들이기
글쓴이: girneter / 작성시간: 월, 2005/07/04 - 2:26오후
제가 MIPS CPU 상에서 embeded device 를 개발중인데
리눅스를 포팅해서 개발할때는 아무 문제 없던 코드가
다른 embeded os 위에 포팅하니 문제를 일으키네요
typedef unsigned char uchar; typedef unsigned short ushort; uchar* ptr = (uchar*) malloc( 100 ); int pos = 1; ushort val = *( (ushort*) (ptr + pos) );
원하는건 8bit pointer 가 가리키는 스트림이 있고
그 중 특정 부분(pos 는 임의의 정수입니다)
에서 16 bit 를 읽어내고 싶은것인데
위와같이 하면 프로그램이 죽어버립니다
메시지를 찍지 않아서 정확히는 알수 없지만
pos 가 홀수일때 문제가 되는걸로 봐서
아마도 memory align 같은 건가봅니다
궁금한것은요,
C 표준에서는 저게 반드시 성공해야 하는것인가요
아니면 OS 나 플랫폼에 따라 안될수도 있는건가요
그러니까 제가 포팅중인 OS 나 C 라이브러리에
오류가 있는건지
원래 안될수도 있는건지가 알고 싶습니다
그리고 ptr 을 ushort* 로 캐스팅하지 않고
1byte 씩만 읽으면 아무 문제가 없는데
그런 전제하에
임의의 위치에서 16 bit 나 32 bit 값을 읽고 싶다면
어떻게 짜는것이 가장 효율적일까요?
Forums:
제 생각에도 정렬 문제 같습니다. (에러 메시지가 버스 에러라면 확실할
제 생각에도 정렬 문제 같습니다. (에러 메시지가 버스 에러라면 확실할 듯.)
일단 이 코드의 결과는 정의되지 않습니다.
캐스팅 없이 memcpy()를 쓰면 될 것 같네요.
memcpy(&val, ptr + pos, 2);
그런데 endian 문제는 고려하지 않아도 되나요?
플랫폼에 따라 될 수도, 안 될 수도 있습니다.제 경험상으로는 R
플랫폼에 따라 될 수도, 안 될 수도 있습니다.
제 경험상으로는 RISC CPU의 경우 대부분은 안 되더군요.
segment fault 혹은 bus error를 뿜어내며 죽어버렸습니다.
그리고, 지원 된다고 하더라도 느려진다고 하더군요.(x86의 경우 저렇게해도 문제는 안 생깁니다. 단, 느려집니다.)
게다가, little endian이냐 big endian이냐에따라 전혀 다른 결과가 나오는 코드입니다.
안전하게 하시려면,
이런 식으로 하시는 게 좋겠습니다.
단, 읽어들일 데이터의 byte order에 따라 위의 코드는 바뀌어야 합니다. 그러나, 읽어들일 데이터의 byte order만 신경쓰면 되고, 프로그램이 동작하는 플랫폼이나 CPU의 byte order에 대해서는 신경쓸 필요가 없습니다.
참고로, 위의 예는 읽어들일 데이터가 little endian의 byte order일 경우의 코드입니다.
[quote]임의의 위치에서 16 bit 나 32 bit 값을 읽고
embeded device 인 경우는 regisiter의 크기가 어느 정도인가요?
8bit regisiter에서 16bit를 읽어 들일수 있는지 아니면
메모리 대 메모리 계산을 할 수 있는 명령이 있는지에 따라 달라 질 것으로봅니다.
C에 많은 경험이 없다보니 잘못된 것이 있으면 바로 잡아 주시기 바랍니다.
댓글 달기