From: <st...@sk...> - 2011-05-04 02:25:44
|
Hi, I have to transmit an unsigned long as four bytes, so I split them up and join them again, but with the folowing example code, I get overflow at long_counter>32767 - can any of you give me a clue how to do it right? <http://code.google.com/p/kodak-timer/source/browse/ir_test/four_unsigned_char_to_unsigned_long.c> unsigned char i; unsigned long long_counter; unsigned char char_counter[4]; void main(void) { unsigned char len; unsigned char lcd_buf[16]; OSCCONbits.SCS = 0x0; // System Clock Select bits = External oscillator OSCCONbits.IRCF = 0x7; // Internal Oscillator Frequency Select bits 8 MHz (INTOSC drives clock directly) lcd_init(); while (1) { for (long_counter = 0; long_counter < 0xffff0000; long_counter += 50) { // split long_counter to four unsigned char's for (i = 0; i < 4; i++) { char_counter[i] = (long_counter & (0xff << (i * 8))) >> (i * 8); } // convert them to unsigned int again long_counter = char_counter[0] | (char_counter[1] << 8) | (char_counter[2] << 16) | (char_counter[3] << 24); sprintf(lcd_buf, "%lu", long_counter); debug(lcd_buf); } } } P.S. Compiling for pic18f2550 - kristoffer ek |
From: Erik P. <epe...@iv...> - 2011-05-04 04:40:12
|
On Wed, 4 May 2011, st...@sk... wrote: > Hi, I have to transmit an unsigned long as four bytes, so I split them up > and join them again, but with the folowing example code, I get overflow at > long_counter>32767 - can any of you give me a clue how to do it right? > // split long_counter to four unsigned char's > for (i = 0; i < 4; i++) { > char_counter[i] = (long_counter & (0xff << (i * 8))) >> (i * 8); > } > > // convert them to unsigned int again > long_counter = char_counter[0] | (char_counter[1] << 8) | > (char_counter[2] << 16) | (char_counter[3] << 24); > Your code for splitting the long into chars should work, but SDCC can optimize this much better: char_counter[0] = long_counter; char_counter[1] = long_counter >> 8; char_counter[2] = long_counter >> 16; char_counter[3] = long_counter >> 24; The problem you are having putting them back together is due to the C integer promotion rules. Although you store the final result into a variable of type long, all of the math leading up to that result will be calculated with an int sized intermediary. Typecasting is needed to explicitly promote the values to a larger type so that the intermediary compuation does not overflow: long_counter = (char_counter[0] | (char_counter[1] << 8)) | ((unsigned long)(char_counter[2] | (char_counter[3] << 8)) << 16); This combines pairs of bytes into two int sized values, then promotes one of them to a long sized value (the other will then also be promoted to the same size automatically) before combining them into a single long. Erik |
From: Kristoffer Ek <st...@sk...> - 2011-05-04 22:46:13
|
On 4.5.2011, at 6:20, Erik Petrich wrote: > long_counter = (char_counter[0] | (char_counter[1] << 8)) | > ((unsigned long)(char_counter[2] | (char_counter[3] << 8)) << 16); This overflows at 32767 :-/ -- stoffer |
From: Erik P. <epe...@iv...> - 2011-05-05 02:31:40
|
On Thu, 5 May 2011, Kristoffer Ek wrote: > > On 4.5.2011, at 6:20, Erik Petrich wrote: > >> long_counter = (char_counter[0] | (char_counter[1] << 8)) | >> ((unsigned long)(char_counter[2] | (char_counter[3] << 8)) << 16); > > > This overflows at 32767 :-/ > > -- stoffer Sorry, I didn't take into account there would be a sign extension in the first half. Try this instead: long_counter = (unsigned int)(char_counter[0] | (char_counter[1] << 8)) | ((unsigned long)(char_counter[2] | (char_counter[3] << 8)) << 16); Erik |
From: Kevin B. <ke...@gm...> - 2011-05-05 04:09:11
|
On Wed, May 4, 2011 at 7:31 PM, Erik Petrich <epe...@iv...> wrote: > > > long_counter = (unsigned int)(char_counter[0] | (char_counter[1] << 8)) | > ((unsigned long)(char_counter[2] | (char_counter[3] << 8)) << 16); I hope the first (unsigned int) cast isn't necessary, because the char_counter[1] << 8 would overflow if it wasn't implicitly an int. |
From: Erik P. <epe...@iv...> - 2011-05-05 05:09:39
|
On Wed, 4 May 2011, Kevin Bailey wrote: > On Wed, May 4, 2011 at 7:31 PM, Erik Petrich > <epe...@iv...> wrote: >> >> long_counter = (unsigned int)(char_counter[0] | (char_counter[1] << 8)) | >> ((unsigned long)(char_counter[2] | (char_counter[3] << 8)) << 16); > > I hope the first (unsigned int) cast isn't necessary, because the > char_counter[1] << 8 would overflow if it wasn't implicitly an int. Yes, char_counter[1] << 8 is implicitly an int. The cast is needed to force it to be unsigned. Otherwise during conversion from (signed) int to unsigned long the most significant bit of the int result will be copied to all of the bits in the upper half of the long, which could then interfere with the bytes from char_counter[2] and char_counter[3]. Converting from unsigned int to unsigned long will force all the bits in the upper half of the long to 0, so no interference. My original suggestion omitted this cast and failed because I forgot to take this signed int to unsigned long behaviour into account. Erik |
From: Hynek S. <ec...@ce...> - 2011-05-05 05:32:13
|
Hi, I would use something like: for (i=0; i<4; i++) char_counter[i] = ((unsigned char*)&long_counter)[i]; for (i=0; i<4; i++) ((unsigned char*)&long_counter)[i] = char_counter[i]; Hynek Dne 4.5.2011 4:08, st...@sk... napsal(a): > Hi, I have to transmit an unsigned long as four bytes, so I split them up > and join them again, but with the folowing example code, I get overflow at > long_counter>32767 - can any of you give me a clue how to do it right? > > <http://code.google.com/p/kodak-timer/source/browse/ir_test/four_unsigned_char_to_unsigned_long.c> > > unsigned char i; > unsigned long long_counter; > unsigned char char_counter[4]; > > void main(void) { > unsigned char len; > unsigned char lcd_buf[16]; > > OSCCONbits.SCS = 0x0; // System Clock Select bits = External oscillator > OSCCONbits.IRCF = 0x7; // Internal Oscillator Frequency Select bits 8 > MHz (INTOSC drives clock directly) > > lcd_init(); > while (1) { > for (long_counter = 0; long_counter< 0xffff0000; long_counter += 50) { > // split long_counter to four unsigned char's > for (i = 0; i< 4; i++) { > char_counter[i] = (long_counter& (0xff<< (i * 8)))>> (i * 8); > } > > // convert them to unsigned int again > long_counter = char_counter[0] | (char_counter[1]<< 8) | > (char_counter[2]<< 16) | (char_counter[3]<< 24); > sprintf(lcd_buf, "%lu", long_counter); > debug(lcd_buf); > } > } > } > > P.S. Compiling for pic18f2550 > > - kristoffer ek |
From: Krishnendu C. <kri...@gm...> - 2011-05-05 07:10:11
|
Hi, My solution would be: #include <stdint.h> union U8x4_n_U32 { uint8_t u8[4]; uint32_t u32; }; union U8x4_n_U32 u8x4_n_u32; // uint32_t to array of uint8_t conversion u8x4_n_u32.u32 = 0xA0459201; /********************************************** ** Now you can access the individual bytes as ** u8x4_n_u32.u8[0] ** u8x4_n_u32.u8[1] ** u8x4_n_u32.u8[2] ** u8x4_n_u32.u8[3] **********************************************/ AND // Array of uint8_t to uint32_t conversion u8x4_n_u32.u8[0] = 0x01; u8x4_n_u32.u8[1] = 0x92; u8x4_n_u32.u8[2] = 0x45; u8x4_n_u32.u8[3] = 0xA0; /********************************************************** ** Now you can access all the bytes as unsigned long using ** u8x4_n_u32.u32 ***********************************************************/ Krish On Thu, May 5, 2011 at 10:48 AM, Hynek Sladky <ec...@ce...> wrote: > Hi, > > I would use something like: > > > for (i=0; i<4; i++) > char_counter[i] = ((unsigned char*)&long_counter)[i]; > > for (i=0; i<4; i++) > ((unsigned char*)&long_counter)[i] = char_counter[i]; > > Hynek > > > Dne 4.5.2011 4:08, st...@sk... napsal(a): > > Hi, I have to transmit an unsigned long as four bytes, so I split them up > and join them again, but with the folowing example code, I get overflow at > long_counter>32767 - can any of you give me a clue how to do it right? > <http://code.google.com/p/kodak-timer/source/browse/ir_test/four_unsigned_char_to_unsigned_long.c> <http://code.google.com/p/kodak-timer/source/browse/ir_test/four_unsigned_char_to_unsigned_long.c> > > unsigned char i; > unsigned long long_counter; > unsigned char char_counter[4]; > > void main(void) { > unsigned char len; > unsigned char lcd_buf[16]; > > OSCCONbits.SCS = 0x0; // System Clock Select bits = External oscillator > OSCCONbits.IRCF = 0x7; // Internal Oscillator Frequency Select bits 8 > MHz (INTOSC drives clock directly) > > lcd_init(); > while (1) { > for (long_counter = 0; long_counter < 0xffff0000; long_counter += 50) { > // split long_counter to four unsigned char's > for (i = 0; i < 4; i++) { > char_counter[i] = (long_counter & (0xff << (i * 8))) >> (i * 8); > } > > // convert them to unsigned int again > long_counter = char_counter[0] | (char_counter[1] << 8) | > (char_counter[2] << 16) | (char_counter[3] << 24); > sprintf(lcd_buf, "%lu", long_counter); > debug(lcd_buf); > } > } > } > > P.S. Compiling for pic18f2550 > > - kristoffer ek > > > > ------------------------------------------------------------------------------ > WhatsUp Gold - Download Free Network Management Software > The most intuitive, comprehensive, and cost-effective network > management toolset available today. Delivers lowest initial > acquisition cost and overall TCO of any competing solution. > http://p.sf.net/sfu/whatsupgold-sd > _______________________________________________ > Sdcc-user mailing list > Sdc...@li... > https://lists.sourceforge.net/lists/listinfo/sdcc-user > > |
From: Philipp K. K. <pk...@sp...> - 2011-05-05 07:40:22
|
Am 05.05.2011 09:10, schrieb Krishnendu Chatterjee: > Hi, > > My solution would be: > > #include <stdint.h> > > union […] This seems to be the best so far, but none of the presented "solutions" from this thread is portable or good C. Here's one that is: unsigned char c[sizeof(unsigned long)]; unsigned long i; memcpy(c, &i, sizeof(unsigned long)); memcpy(&i, c, sizeof(unsigned long)); Philipp |
From: Krishnendu C. <kri...@gm...> - 2011-05-05 07:52:01
|
Hi, I don't understand what do you mean by "PORTABLE". Union is supported in sdcc, gnu-arm, gcc and visual C. And I have not seen any document stating that the usage of union in C is bad :) Krish On Thu, May 5, 2011 at 1:10 PM, Philipp Klaus Krause <pk...@sp...> wrote: > Am 05.05.2011 09:10, schrieb Krishnendu Chatterjee: > > Hi, > > > > My solution would be: > > > > #include <stdint.h> > > > > union […] > > This seems to be the best so far, but none of the presented "solutions" > from this thread is portable or good C. Here's one that is: > > unsigned char c[sizeof(unsigned long)]; > unsigned long i; > > memcpy(c, &i, sizeof(unsigned long)); > memcpy(&i, c, sizeof(unsigned long)); > > Philipp > > > ------------------------------------------------------------------------------ > WhatsUp Gold - Download Free Network Management Software > The most intuitive, comprehensive, and cost-effective network > management toolset available today. Delivers lowest initial > acquisition cost and overall TCO of any competing solution. > http://p.sf.net/sfu/whatsupgold-sd > _______________________________________________ > Sdcc-user mailing list > Sdc...@li... > https://lists.sourceforge.net/lists/listinfo/sdcc-user > |
From: Philipp K. K. <pk...@sp...> - 2011-05-05 08:03:49
|
Am 05.05.2011 09:51, schrieb Krishnendu Chatterjee: > Hi, > > I don't understand what do you mean by "PORTABLE". Union is supported in > sdcc, gnu-arm, gcc and visual C. > And I have not seen any document stating that the usage of union in C is > bad :) > The problem is not the union. However uint8_t and uint32_t might not be there (unlike e.g. uint_least8_t or uint_least32_t, which are required). E.g. when an architecture has no 8-bit data type, this could happen: sizeof(unsiged char) == sizeof(uint_least8_t) == sizeof(unsigned int) == sizeof(uint16_t) == 1 Philipp |
From: Maarten B. <sou...@ds...> - 2011-05-05 09:43:39
|
Hi all, When portability is an issue my concerns would be endianness and packing which none of the posts have addressed. C does not guarantee much about the position of fields in a union or a struct or the position of bytes in a long int. Maarten > Am 05.05.2011 09:10, schrieb Krishnendu Chatterjee: >> Hi, >> >> My solution would be: >> >> #include <stdint.h> >> >> union [ ] > > This seems to be the best so far, but none of the presented "solutions" > from this thread is portable or good C. Here's one that is: > > unsigned char c[sizeof(unsigned long)]; > unsigned long i; > > memcpy(c, &i, sizeof(unsigned long)); > memcpy(&i, c, sizeof(unsigned long)); > > Philipp > > ------------------------------------------------------------------------------ > WhatsUp Gold - Download Free Network Management Software > The most intuitive, comprehensive, and cost-effective network > management toolset available today. Delivers lowest initial > acquisition cost and overall TCO of any competing solution. > http://p.sf.net/sfu/whatsupgold-sd > _______________________________________________ > Sdcc-user mailing list > Sdc...@li... > https://lists.sourceforge.net/lists/listinfo/sdcc-user > > |
From: Krishnendu C. <kri...@gm...> - 2011-05-05 14:29:07
|
Hi, stdint.h is a standard C header file. If you use it in VC, you need to download it from net and place it in the include folder. If packing of struct is necessory, use "#pragma pack" compiler directive to resolve it. For example, #include <stdint.h> #pragma pack(1) union U8x4_n_U32 { uint8_t u8[4]; uint32_t u32; }; #pragma pack() SDCC will ignore the pragmas with an warning. GCC and VC would accept it without any problem. I have to think about the endian-ness problem. Most probably I would write some #ifdef kind of statement to compile the specific part of the code that converts a long to its constituent bytes. Krish On Thu, May 5, 2011 at 3:13 PM, Maarten Brock <sou...@ds...>wrote: > Hi all, > > When portability is an issue my concerns would be endianness and packing > which none of the posts have addressed. C does not guarantee much about > the position of fields in a union or a struct or the position of bytes in > a long int. > > Maarten > > > Am 05.05.2011 09:10, schrieb Krishnendu Chatterjee: > >> Hi, > >> > >> My solution would be: > >> > >> #include <stdint.h> > >> > >> union […] > > > > This seems to be the best so far, but none of the presented "solutions" > > from this thread is portable or good C. Here's one that is: > > > > unsigned char c[sizeof(unsigned long)]; > > unsigned long i; > > > > memcpy(c, &i, sizeof(unsigned long)); > > memcpy(&i, c, sizeof(unsigned long)); > > > > Philipp > > > > > ------------------------------------------------------------------------------ > > WhatsUp Gold - Download Free Network Management Software > > The most intuitive, comprehensive, and cost-effective network > > management toolset available today. Delivers lowest initial > > acquisition cost and overall TCO of any competing solution. > > http://p.sf.net/sfu/whatsupgold-sd > > _______________________________________________ > > Sdcc-user mailing list > > Sdc...@li... > > https://lists.sourceforge.net/lists/listinfo/sdcc-user > > > > > > > > ------------------------------------------------------------------------------ > WhatsUp Gold - Download Free Network Management Software > The most intuitive, comprehensive, and cost-effective network > management toolset available today. Delivers lowest initial > acquisition cost and overall TCO of any competing solution. > http://p.sf.net/sfu/whatsupgold-sd > _______________________________________________ > Sdcc-user mailing list > Sdc...@li... > https://lists.sourceforge.net/lists/listinfo/sdcc-user > |