supersonic 0 Posted March 11, 2013 Share Posted March 11, 2013 Hi, I'm new to this platform, I love it, it's cheap and powerful enough for my needs. I'm also trying to improve my C knowledge, I've using PicBasic a lot and I'm much more familiar with it I'm trying to assign the 4 bytes of a long int to 4 different variables. I've been looking on the Internet for a solution and apparently I found it. Here's the code that SHOULD work: byte aa,bb,cc,dd; long int cast = 0xAABBCCDD; void loop(){ aa = (byte) cast >> 24; bb = (byte) cast >> 16; cc = (byte) cast >> 8; dd = (byte) cast; Serial.print("cast= "); Serial.print(cast, HEX); Serial.print(" a="); Serial.print(aa, HEX); Serial.print(" b="); Serial.print(bb, HEX); Serial.print(" c="); Serial.print(cc, HEX); Serial.print(" d="); Serial.print(dd, HEX); } What I get on the serial monitor(I'm using an MSP430g2553 to have Hardware UART) is this:cast= AABBCCDD a=0 b=0 c=0 d=DD Where am I wrong? Quote Link to post Share on other sites
oPossum 1,083 Posted March 11, 2013 Share Posted March 11, 2013 aa = (byte) (cast >> 24); bb = (byte) (cast >> 16); cc = (byte) (cast >> 8); dd = (byte) cast; faster code: byte *p = (byte *)&cast; dd = *p++; cc = *p++; bb = *p++; aa = *p; Cw1X 1 Quote Link to post Share on other sites
olivluca 12 Posted March 11, 2013 Share Posted March 11, 2013 I'm not familiar enough with C, but I think the "(byte) cast", just casts "cast" before shifting, hence only the last bytes shows., i.e. your code is equivalent to aa = 0xDD >> 24; bb = 0xDD >> 16; cc = 0xDD >> 8; dd = 0xDD cast; Maybe you could try aa = (byte) (cast >> 24); bb = (byte) (cast >> 16); cc = (byte) (cast >> 8); dd = (byte) cast; note the extra parenthesis. Edit: oPossum beat me, but I don't like the last solution since it's not portable. Aren't there standard functions/macros that do this taking care of the endianness of the target system? Quote Link to post Share on other sites
semicolo 39 Posted March 11, 2013 Share Posted March 11, 2013 Forget about this line, wrote something stupid and can't remove it. Quote Link to post Share on other sites
roadrunner84 466 Posted March 11, 2013 Share Posted March 11, 2013 aa = (byte) (cast >> 24); bb = (byte) (cast >> 16); cc = (byte) (cast >> 8); dd = (byte) cast; faster code: byte *p = (byte *)&cast; dd = *p++; cc = *p++; bb = *p++; aa = *p; The second code may be a little faster, but it is less portable: you assume that the least significant byte is at the first memory location, this may be true for the msp430, but you cannot relyon this being the case on any other platform. I suggest you use the first code over the second one. Quote Link to post Share on other sites
oPossum 1,083 Posted March 11, 2013 Share Posted March 11, 2013 Neither method is portable - they both rely upon undefined behavior of the C compiler. As a practical matter they are equally portable. The only popular big endian microcontoller was the M68k series, and it is essentially dead. If you think there is a small difference in code size and speed - just look at the asm code generated by the compiler... Quote Link to post Share on other sites
supersonic 0 Posted March 12, 2013 Author Share Posted March 12, 2013 Thanks for the quick answer guys. It works now! I will use the "slower" version of the code. As I'll be familiar with pointers I will use the "faster" version. Quote Link to post Share on other sites
ike 53 Posted March 13, 2013 Share Posted March 13, 2013 union mix_t { long l; struct { short hi; short lo; } s; char c[4]; } mix; Source: http://www.cplusplus.com/doc/tutorial/other_data_types/ Quote Link to post Share on other sites
pabigot 355 Posted March 13, 2013 Share Posted March 13, 2013 Source: http://www.cplusplus.com/doc/tutorial/other_data_types/ Not ideal. Don't assume you know how big int, short, and long are. I know there's a tendency in the microcontroller world to use long as if it were mandated to be 32 bits and short as mandated to be 16 bits, but it just ain't so. Also, try to avoid signed integers when you're extracting bits from a multi-octet integral type: sign preservation in right shifts may be costly and can bleed into the output if you don't remember to mask off the upper bits. #include <stdint.h> union breakdown32_t { uint32_t d32[1]; uint16_t d16[2]; uint8_t d8[4]; }; roadrunner84 and spirilis 2 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.