[완료] char[4]에 담긴 값을 int로 변환할 때...

linuxgeek의 이미지

little endian으로 표기된 특정 4바이트를 읽어 와서 int값으로 변환하는 방법을 좀 알려 주십시요.

예를 들어.

0x01 0x00 0x00 0xFF 라는 값을 각각 char[0] char[1] char[2] char[3]에 담았다고 할 때.

little endian이니까 0xFF 0x00 0x00 0x01로 revert 시킨 다음 int i = (int) test; 하면 되지 않을까라는 생각을 해 봤는데 역시 말도 안되는 방법이었던 거 같네요.

아무래도 int i = 0; 에다 char를 하나씩 쉬프트해 넣는거 같은데 워낙 비트 연산에 약해서 잘 모르겠습니다.

쉽게 설명 좀 부탁 드리겠습니다.

sixmen의 이미지

메모리상에 0x01, 0x02, 0x03, 0x04 순서로 있다면

char mem[] = { 0x01, 0x02, 0x03, 0x04 };

이걸 그냥 int *로 간주하고 값을 얻으면 됩니다.

int val = * (int *)mem;

이러면 val==0x04030201 이 됩니다.
반면 big endian 시스템이라면 val==0x01020304 가 되고요.

순서를 바꿀 필요가 있는 건 메모리 상의 저장 값과 시스템이 서로 다른 endian을 가지고 있을 때 뿐입니다.

다만 이 방법은 문제 소지가 있습니다. memory align이 맞지 않으면 죽는 시스템이 있습니다.
예를 들어 mem의 주소가 0x10000이면 괜찮은데, 0x10001이면 죽을 수 있다는 거죠..
(x86을 쓰는 PC는 괜찮지만, 모바일 기기에 많이 쓰이는 ARM은 문제가 발생합니다)

이경우 비트 연산이 필요한데 너무 어렵게 생각하지 않으셔도 됩니다.

val = 0x04030201 = 0x04000000 | 0x030000 | 0x0200 | 0x01 = (mem[3]<<24) | (mem[2]<<16) | (mem[1]<<8) | mem[0];

입니다. 만약에 메모리 값을 big endian으로 해석하고 싶다면

val = 0x01020304 = (mem[0]<<24) | (mem[1]<<16) | (mem[2]<<8) | mem[3];

이 되겠죠. *(int *)가 시스템의 endian에 따라 결과가 달라진다면 bit shift를 쓰는 방식은 endian의 영향을 받지 않는 장점이 있죠.

linuxgeek의 이미지

자세한 답변 감사 드립니다. 많은 도움이 되었습니다.

===================================================================
8-bit

===================================================================
8-bit

sajacall82의 이미지

union을 활용해 보세요.

#include

union Test {
int x;
char y[4];
};

int main() {
int i;
union Test t1;

t1.x = 10;
printf("%d\n", t1.x);
for( i = 0; i<4; i++) {
printf("%02x\n", t1.y[i]&0x0ff );
}

return 0;
}

순간을 지배하는 사람이 인생을 지배한다.

linuxgeek의 이미지

한 번도 써 본적이 없지만 union을 사용하면 되는군요.

아이디어 감사 드립니다.

===================================================================
8-bit

===================================================================
8-bit

체스맨의 이미지

int val = * (int *)mem;

이것은 좋은 방법이 아닙니다.
정렬 문제 때문에 시스템에 따라 bus error 등이 유발될 수도 있기 때문입니다.

비트 연산을 쓰시는 것이 정석입니다.

Orion Project : http://orionids.org

linuxgeek의 이미지

테스트를 해 봤는데 제가 뭘 잘못 한건지 생각하던 결과가 아닌데요. 뭐가 잘못 되었을까요?

int main()
{
    char a[4];
    a[0] = 0xD4;
    a[1] = 0xC3;
    a[2] = 0xB2;
    a[3] = 0xA1;
 
    int i = 0, j = 0; 
 
    i = a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3];
    j = a[3] << 24 | a[2] << 16 | a[1] << 8 | a[0];
 
    printf("i = a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3]: %X\r\n", i);
    printf("i = a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3]: %d\r\n", i);
    printf("\r\n");
    printf("j = a[3] << 24 | a[2] << 16 | a[1] << 8 | a[0]: %X\r\n", j);
    printf("j = a[3] << 24 | a[2] << 16 | a[1] << 8 | a[0]: %d\r\n", j);
}

결과:
[fedora9]$ ./base 
i = a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3]: FFFFFFA1
i = a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3]: -95
 
j = a[3] << 24 | a[2] << 16 | a[1] << 8 | a[0]: FFFFFFD4
j = a[3] << 24 | a[2] << 16 | a[1] << 8 | a[0]: -44

===================================================================
8-bit

===================================================================
8-bit

정태영의 이미지

어라 신기하게도 shift한 다음에 보니 상위 비트가 1로 채워지네요. 아래처럼 해보세요.

i = (a[0] << 24)&0xFF000000 | (a[1] << 16)&0xFF0000 | (a[2] << 8)&FF00 | (a[3])&0xFF

--
오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

linuxgeek의 이미지

아 그렇군요. 그럼 unsigned char로 하면 되겠네요.

답변 감사 드립니다.

===================================================================
8-bit

===================================================================
8-bit

gardner의 이미지

비트 연산이 싫으시면 256씩 곱해 나가면서 더하면 됩니다.
256진법이라 생각하면 쉽죠.
물론 char, int 둘다 unsigned 형이어야 합니다.

그리고 unsigned int형 보다는 stdint.h에 정의된 uint32_t 형을 춫헌...

uint32_t i = ( ( ( (uint32_t)a[0] * 256) + a[1]) * 256 + a[2]) * 256 + a[3];

만약 사용하시는 플랫폼에서 제공하는 리틀/빅 엔디안 변환 함수가 있다면
웬만하면 그걸 사용하시는 쪽을 강추합니다.

댓글 달기

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 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • 사용할 수 있는 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>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • You can use Textile markup to format text.
  • 사용할 수 있는 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>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 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>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.