8bit 포인터에서 16 bit 값 읽어들이기

girneter의 이미지

제가 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 값을 읽고 싶다면
어떻게 짜는것이 가장 효율적일까요?

doldori의 이미지

제 생각에도 정렬 문제 같습니다. (에러 메시지가 버스 에러라면 확실할 듯.)
일단 이 코드의 결과는 정의되지 않습니다.

Quote:
C99 6.3.2.3/7

A pointer to an object or incomplete type may be converted to a pointer
to a different object or incomplete type. If the resulting pointer is not
correctly aligned for the pointed-to type, the behavior is undefined.


캐스팅 없이 memcpy()를 쓰면 될 것 같네요.
memcpy(&val, ptr + pos, 2);
그런데 endian 문제는 고려하지 않아도 되나요?
espereto의 이미지

플랫폼에 따라 될 수도, 안 될 수도 있습니다.

제 경험상으로는 RISC CPU의 경우 대부분은 안 되더군요.
segment fault 혹은 bus error를 뿜어내며 죽어버렸습니다.

그리고, 지원 된다고 하더라도 느려진다고 하더군요.(x86의 경우 저렇게해도 문제는 안 생깁니다. 단, 느려집니다.)

게다가, little endian이냐 big endian이냐에따라 전혀 다른 결과가 나오는 코드입니다.

안전하게 하시려면,

ushort val = *(ptr) | (*(ptr + 1) << 8);

이런 식으로 하시는 게 좋겠습니다.

단, 읽어들일 데이터의 byte order에 따라 위의 코드는 바뀌어야 합니다. 그러나, 읽어들일 데이터의 byte order만 신경쓰면 되고, 프로그램이 동작하는 플랫폼이나 CPU의 byte order에 대해서는 신경쓸 필요가 없습니다.

참고로, 위의 예는 읽어들일 데이터가 little endian의 byte order일 경우의 코드입니다.

lovewar의 이미지

Quote:

임의의 위치에서 16 bit 나 32 bit 값을 읽고 싶다면
어떻게 짜는것이 가장 효율적일까요?

embeded device 인 경우는 regisiter의 크기가 어느 정도인가요?

8bit regisiter에서 16bit를 읽어 들일수 있는지 아니면
메모리 대 메모리 계산을 할 수 있는 명령이 있는지에 따라 달라 질 것으로봅니다.

C에 많은 경험이 없다보니 잘못된 것이 있으면 바로 잡아 주시기 바랍니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.