c - Casting negative numbers -
i trying interpret hex bytes , consolidate them useful information.
void processdata(){ signed char data; unsigned long a;//holds 4 bytes unsigned long b; unsigned int c;//holds 2 bytes unsigned char d;//holds 1 byte a=reada();//reada,readb,readc,readd return 1 unsigned byte; b=readb(); c=readc(); d=readd(); data=(signed char) ((0xffffffff-((a<<24)|(b<<16)|(c<<8)|(d)))/1000); }
the scenario whole package received contains four-byte information, example value of 0xaabbccdd. reada() return highest byte in package i.e. 0xaa. readd() return 0xdd. need shift them before using "|" put them together: (a<<24)|(b<<16)|(c<<8)|(d)
so question is, right hand side of sentence
data=(signed char) ((0xffffffff-((a<<24)|(b<<16)|(c<<8)|(d)))/1000);
why not return char while cast result signed char? when print out wrong. however, if set data
signed long, correct. guess it's because signed char not big enough hold information , caused overflows.
correct me if wrong, variables in ((a<<24)|(b<<16)|(c<<8)|(d)))
implicitly cast unsigned long , result of expression. ((a<<24)|(b<<16)|(c<<8)|(d)))/1000
return unsigned long number. result smaller since it's divided 1000.
the four-byte information ranges 0xffff5037 0xffffffff, range of result of expression ((a<<24)|(b<<16)|(c<<8)|(d)))
.
so right hand side of expression should between 0 45 after division done. when print result it's jumping around.
6.3.1.3 signed , unsigned integers
1 when value integer type converted integer type other _bool, if value can represented new type, unchanged. 2 otherwise, if new type unsigned, value converted repeatedly adding or subtracting 1 more maximum value can represented in new type until value in range of new type. 3 otherwise, new type signed , value cannot represented in it; either result implementation-defined or implementation-defined signal raised.
the code you've given might behave in different ways depending on choices made implementations use. it's not unreasonable see implementation raising implementastion-defined signal corresponding exceptional condition, such sigsegv. if implementation decides default action ignore signal, lay in realm of undefined behaviour implementation.
do calculation in longer types, convert longer value smaller value reducing modulo correct width, , adding schar_min produce negative values if necessary. (read comments)
void processdata(){ signed char data; unsigned long a; // holds sizeof (unsigned long) bytes* unsigned long b; unsigned int c; // holds sizeof (int) bytes* unsigned char d; // holds 1 byte // footnote: int , unsigned long might have padding bits // --------- attempting modify padding bits can // result in undefined behavior... = (reada() << 24) + (readb() << 16) + (readc() << 8) + d; /= 1000; %= uchar_max; if (a <= schar_max) { // value fit safely data per point 1 of 6.3.1.3 data = a; } else if (a >= (unsigned char) schar_min) { // since converting negative values positive values result // in values greater or equal (unsigned char) schar_min, // reducing modulo // (unsigned char) schar_min work out how many add schar_min. data = schar_min + (a % (unsigned char) schar_min); } else { // value out of range. perhaps corresponds negative zero? data = 0; } }
the last condition-chain can shortened to:
data = <= schar_max ? : >= (unsigned char) schar_min? schar_min +(a % (unsigned char) schar_min) : 0;
Comments
Post a Comment