में इस सवाल का जवाब , zwol इस दावे किए गए:
बाहरी स्रोत से डेटा के दो बाइट्स को 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
क्रियान्वयन-परिभाषित करते समय सटीक व्यवहार , इसलिए भोला दृष्टिकोण पोर्टेबल नहीं है।