2014-11-18 5 views
1

C/C++에서 char 배열을 어떤 위치에서 int로 변환 할 수 있습니까?정렬되지 않은 위치에서 char 배열을 int로 변환하는 방법은 무엇입니까?

unsigned char data[8]; 
data[0] = 0; data[1] = 1; ... data[7] = 7; 
int32_t p = 3; 
int32_t d1 = *((int*)(data+3)); // = 0x03040506 CORRECT 
int32_t d2 = *((int*)(data+p)); // = 0x00010203 WRONG 

업데이트 :

은 내가 const가 아닌 오프셋 (offset) 포인터 연산을 사용하려고하면 자동으로 (32 비트 아키텍처에) 가장 가까운 32 비트에 맞춰 비트, 다음 시도
  • 의견에서 언급했듯이 입력은 3의 튜플로 제공되며 나는 을 변경할 수 없습니다.
  • 처리를 위해 3 개의 값을 int로 변환하고이 변환을 최대한 빨리 수행해야합니다.
  • 솔루션은 크로스 플랫폼 일 필요는 없습니다. 나는 매우 특정 컴파일러와 프로세서로 작업 중이므로 big endian을 가진 32 비트 아키텍처라고 가정 할 수 있습니다.
  • 결과의 최하위 바이트는 중요하지 않습니다 (위 참조).

현재 나의 주요 질문은 다음과 같습니다. 왜 d1에 올바른 값이 있지만 d2가 아닌가? 다른 컴파일러에서도 마찬가지입니까? 이 행동을 바꿀 수 있습니까?

+2

** 중재자 주처럼 엔디 언 불가지론 방법으로 일을하는 것이 더 쉬울 것입니다 ** : 의견이 양도되었습니다. 삭제되었습니다. 답변이 있으면 게시하십시오. 더 좋은 방법있으세요? 답으로 게시하십시오! 기회를 잡으세요. –

+0

가능하지 않으므로 정렬 문제를 피하기 위해 한 번에 4 픽셀 씩 작업하여 부분적으로 해결했습니다. – Karsten

+0

이 중 하나가 작동하지 않았다 ... 컴파일러가 2^N 테두리에 정렬하는 것 같습니다. – Karsten

답변

3

아니요 휴대용으로는 불가능합니다.

이 동작은 int*char*에서 캐스팅을 시도 할 때하는 C와 C 모두에서 정의되지 않은입니다 발생 ++ (아마도 당신이 발견 한 바로 그 이유 : int의 가능성이 4 개 바이트 경계에 정렬하고 data 중입니다 물론, 연속.) data+3 작동하지만 data+p하지 않는 런타임 평가 대 시간을 컴파일 할 가능성 때문이라고

(사실.)

는 또한 char의 로그인 다움 특별한 경우의가 아닙니다 d를 C 또는 C++로 작성하면 이런 코드를 작성하는 경우 signed char 또는 unsigned char을 사용해야합니다.

가장 좋은 방법은 intchar 값을 흡수하는 비트 시프트 연산자 (>><<) 및 논리적 |&을 사용하는 것입니다. 또한 16 또는 64 비트 int s의 대상에 빌드 할 경우에 대비하여 int32_t을 사용하는 것도 고려하십시오.

+0

그리고 const 값과 함께 왜 작동합니까? 작동 여부에 관계없이 컴파일러 종속성이 있다고 가정합니까? – Karsten

+0

const 값? 나는 네가 의미하는 것을 이해하지 못한다. – Bathsheba

+0

필자의 예 (적어도 제 컴파일러는) d1은 올바른 값을 가지고 있지만 d2는 그렇지 않습니다. – Karsten

2

잘못된 방법으로 포인터를 변환하는 것은 정의되지 않습니다.

memcpy을 사용하면 char 어레이를 int32_t으로 복사 할 수 있습니다.

int32_t d = 0; 
memcpy(&d, data+3, 4); // assuming sizeof(int) is 4 

대부분의 컴파일러는 일정한 크기의 인수 memcpy에 대한 기능을 내장, 그래서 이것이 어떤 런타임 오버 헤드를 발생하지 않을 가능성이 높습니다.

표시 한 것과 같은 캐스트가 올바르게 정렬 된 포인터에 허용되어 있어도 이러한 포인터를 역 참조하면 엄격한 앨리어싱을 위반하게됩니다. 유효한 유형이 char[] 인 객체는 int 유형의 왼쪽 값을 통해 액세스하면 안됩니다. 일반적으로, 유형 말장난에

엔디안에 의존하고 변환하는 RGB 색상을 나타내는 char 배열

int32_t d = (int32_t)data[2] << 16 | (int32_t)data[1] << 8 | data[0]; 
+0

좋은 생각이 아닙니다. C는'char'가 부호없는 것을 요구하지 않습니다. 'char'가 사인되면'int32_t' 로의 변환은 sign-extend가되어 잠재적으로'd '의 최상위 비트를'|'로 설정합니다. – EOF

+0

불행히도 입력을 변경할 수 없습니다. 그것은 내 경우에 주어진다. 저는 교대로 그것을 할 수 있다는 것을 압니다. 그러나 그것은 훨씬 느리고이 부분은 오히려 성능에 치명적입니다. 데이터가 이미 메모리에서 올바른 순서로 존재하기 때문에 몇 가지 대신 하나의 명령어 만 필요로하는 직접적인 방법이 있기를 바란다. – Karsten

+0

@EOF :'data'는 질문에서'unsigned char'입니다. – mafso

관련 문제