2 바이트의 데이터를 외부 소스에서 16 비트 부호있는 정수로 변환하는 올바른 방법은 다음과 같은 도우미 기능을 사용하는 것입니다.
#include <stdint.h>
int16_t be16_to_cpu_signed(const uint8_t data[static 2]) {
uint32_t val = (((uint32_t)data[0]) << 8) |
(((uint32_t)data[1]) << 0);
return ((int32_t) val) - 0x10000u;
}
int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
uint32_t val = (((uint32_t)data[0]) << 0) |
(((uint32_t)data[1]) << 8);
return ((int32_t) val) - 0x10000u;
}
위의 함수 중 적절한 것은 배열에 리틀 엔디안이 포함되어 있는지 또는 빅 엔디안이 포함되어 있는지에 따라 다릅니다. 엔디안은 여기서 문제가되지 않지만 zwol이로 변환 0x10000u
된 uint32_t
값 에서 빼는 이유가 궁금 합니다 int32_t
.
왜 이것이 올바른 방법 입니까?
반환 유형으로 변환 할 때 구현 정의 동작을 어떻게 피합니까?
2의 보수 표현을 가정 할 수 있으므로이 간단한 캐스트는 어떻게 실패합니까? return (uint16_t)val;
이 순진한 솔루션의 문제점 :
int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
return (uint16_t)data[0] | ((uint16_t)data[1] << 8);
}
int16_t
0xFFFF0001u
으로 표현할 수없고 int16_t
두 번째 방법 0xFFFFu
에서는으로 표현할 수 없습니다 int16_t
.
int16_t
은 구현 정의이므로 순진한 접근 방식은 이식성이 없습니다.