449,173 Members | 1,049 Online
Need help? Post your question and get tips & solutions from a community of 449,173 IT Pros & Developers. It's quick & easy.

# byte array and long??

 P: n/a hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? thanks! Jul 22 '05 #1
9 Replies

 P: n/a "w3r3w0lf" wrote in message news:bv**********@ls219.htnet.hr... hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? thanks! This *might* work, long x = *reinterpret_cast(a + 2); but if it doesn't it is because you have to swap the bytes around. byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes long x = *reinterpret_cast(tmp); john Jul 22 '05 #2

 P: n/a On Tue, 3 Feb 2004 22:28:38 -0000, "John Harrison" wrote in comp.lang.c++: "w3r3w0lf" wrote in message news:bv**********@ls219.htnet.hr... hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? thanks! This *might* work, long x = *reinterpret_cast(a + 2); but if it doesn't it is because you have to swap the bytes around. byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes long x = *reinterpret_cast(tmp); john But it will fail on an ARM (and some other processors) with an addressing fault due to improper alignment. It will fail on a TI 320F28xx because the long will contain 0x003000fe which is not what the OP asked for. And in fact it is undefined behavior on any platform/architecture/implementation. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html Jul 22 '05 #3

 P: n/a "w3r3w0lf" wrote in message news:bv**********@ls219.htnet.hr... hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? thanks! try this and tell me if this works! #include using namespace std; int main(){ char a[] = {0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}; long b=0; memcpy(&b,&a[2], sizeof(4)); cout << b << endl; cin.get(); } ~ Let us linux ~ -----= Posted via Newsfeeds.Com, Uncensored Usenet News =----- http://www.newsfeeds.com - The #1 Newsgroup Service in the World! -----== Over 100,000 Newsgroups - 19 Different Servers! =----- Jul 22 '05 #4

 P: n/a "Jack Klein" wrote in message news:1h********************************@4ax.com... On Tue, 3 Feb 2004 22:28:38 -0000, "John Harrison" wrote in comp.lang.c++: "w3r3w0lf" wrote in message news:bv**********@ls219.htnet.hr... hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? thanks! This *might* work, long x = *reinterpret_cast(a + 2); but if it doesn't it is because you have to swap the bytes around. byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes long x = *reinterpret_cast(tmp); john But it will fail on an ARM (and some other processors) with an addressing fault due to improper alignment. It will fail on a TI 320F28xx because the long will contain 0x003000fe which is not what the OP asked for. And in fact it is undefined behavior on any platform/architecture/implementation. I never claimed my answer was platform independent. A truly platform independent answer is surprisingly difficult. Perhaps you could oblige the OP with such an answer? John Jul 22 '05 #5

 P: n/a On Tue, 03 Feb 2004 23:19:35 +0100, w3r3w0lf wrote: hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? Assuming unsigned char for byte, this should work portably and safely: long l = 0; for (size_t ix=5; ix>1; ++ix) { l <<= 8; l |= a[ix]; } If byte is signed, stick in a cast to unsigned char. HTH, M4 Jul 22 '05 #6

 P: n/a "Martijn Lievaart" wrote in message news:pa****************************@remove.this.pa rt.rtij.nl... On Tue, 03 Feb 2004 23:19:35 +0100, w3r3w0lf wrote: hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? Assuming unsigned char for byte, this should work portably and safely: long l = 0; for (size_t ix=5; ix>1; ++ix) { l <<= 8; l |= a[ix]; } If byte is signed, stick in a cast to unsigned char. HTH, M4 Sorry to be pedantic, but it assumes 8 bits for char. Replace 8 with CHAR_BIT from . Also to be extremely pedantic I don't think that the standard gives any guarantees and to the 'mathematical' behaviour of << when the left argument is long (unsigned long would be different). So there is no guarantee that l <<= 8 is the same as l *= 256. But if you were to replace l <<= 8 with l *= 256 then you would run into undefined behaviour because of the potential overflow (again it would be different with unsigned long). At least that's how I remember it, as usual I can't find the reference in the standard. Sometimes it seems to me that the standard makes simple things very difficult. john Jul 22 '05 #7

 P: n/a On Wed, 04 Feb 2004 08:15:30 +0000, John Harrison wrote: Assuming unsigned char for byte, this should work portably and safely: long l = 0; for (size_t ix=5; ix>1; ++ix) { l <<= 8; l |= a[ix]; } If byte is signed, stick in a cast to unsigned char. Sorry to be pedantic, but it assumes 8 bits for char. Replace 8 with CHAR_BIT from . Good point, but actually depends on the input. If the input is octets (which is quite likely, most of the world talks octets, 8 is correct. Also to be extremely pedantic I don't think that the standard gives any guarantees and to the 'mathematical' behaviour of << when the left argument is long (unsigned long would be different). So there is no guarantee that l <<= 8 is the same as l *= 256. But if you were to replace l <<= 8 with l *= 256 then you would run into undefined behaviour because of the potential overflow (again it would be different with unsigned long). At least that's how I remember it, as usual I can't find the reference in the standard. Right. 5.8 clause two. A left shift shifts left the bit pattern making up the object. The reference to bitpattern makes it clear that this is implementation defined for signed. It even explicitly states that it has defined behaviour for unsigned integers. 5 clause 5. All overflows result in UB. So if the shift-left or the *256 results in a (signed) long that would be greater than LONG_MAX, we enter UB. 3.9.1 clause 4. All unsigned integer types shall obey modulo-2 arithmetic. 3.9.1 clause 3. The bitpatterns for positive signed integers are the same as their unsigned counterpart. So left-shifting works only with unsigned long, and with signed long when the input results in a positive number <= LONG_MAX. It is also guarenteed to work with negative longs if you know for a fact that your machine uses 2's-complement arithmetic, which is a non-portable assumption. Also, if the original bit pattern originated on the same machine, the left-shift solution is required to work with signed long, however, in that case this is musch simpler: long l; memcpy(&l, a+2, sizeof(long)); Multiplying with 256 works for unsigned long, and with signed long when the input results in a positive number <= LONG_MAX. In practice it will work with 2's-complement, but contrary to left-shifting the standard does not guarentee that. Another point to note, is that the standard probably only guarentees the result if the type byte is an unsigned type. If the type byte is a signed char for instance: l |= a[ix]; would convert a[ix] to a signed long, hardly what you want. l |= static_cast(a[ix]); Makes 4.7 clause 2 apply: "2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [Note: In a two s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). ]" Which I don't understand, but clearly implies the bit pattern can change on non-2's-complement machines. Sometimes it seems to me that the standard makes simple things very difficult. Yup. OTOH, this stuff /is/ difficult. Use text formats or network-order if portability is an issue. If using network order, unly use it for unsigned types. M4 Jul 22 '05 #8

 P: n/a On Wed, 04 Feb 2004 07:51:23 +0000, John Harrison wrote: > This *might* work, > > long x = *reinterpret_cast(a + 2); > > but if it doesn't it is because you have to swap the bytes around. > > byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes > long x = *reinterpret_cast(tmp); > > john But it will fail on an ARM (and some other processors) with an addressing fault due to improper alignment. It will fail on a TI 320F28xx because the long will contain 0x003000fe which is not what the OP asked for. And in fact it is undefined behavior on any platform/architecture/implementation. I never claimed my answer was platform independent. A truly platform No, but you indicated that it could fail due to byte order, where it can in fact crash. independent answer is surprisingly difficult. Perhaps you could oblige the OP with such an answer? See the other subthread, where a better answer is discussed. To truly answer the question, we should know more about the input and context. HTH, M4 Jul 22 '05 #9

 P: n/a w3r3w0lf wrote in news:bv**********@ls219.htnet.hr: hello! I have a following situation: I have a byte array where at a certain location are stored 4 bytes, and these should be "put" into long variable (or any other 4 byte one). ie: byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0} and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which should then contain 43921662 how to achieve this? #include #include typedef unsigned char byte; byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}; byte m[] = { 0xB2, 0x9E, 0x43, 0xFF }; /* -12345678 */ long four_bytes_to_long( byte const *bp ) { unsigned long ul = ( bp[0] * 1UL ) + ( bp[1] * 256UL ) + ( bp[2] * 256UL * 256UL ) + ( bp[3] * 256UL * 256UL * 256UL ) ; unsigned long const lmax = std::numeric_limits< long >::max(); return ( ul > lmax ) ? -long(~ul + 1) : long( ul ); } int main() { std::cerr << four_bytes_to_long( a + 2 ) << '\n'; std::cerr << four_bytes_to_long( m ) << '\n'; } HTH. Rob. -- http://www.victim-prime.dsl.pipex.com/ Jul 22 '05 #10

### This discussion thread is closed

Replies have been disabled for this discussion.