Convert four chars to a long and a long to four chars
Author |
Message |
Joseph Cohe #1 / 24
|
 Convert four chars to a long and a long to four chars
if i have an array of four chars, how can i make it a long? the reason i want to do it (transfering numbers on the net) is not c related BUT MY QUESTION IS SO DONT "FLAME" ME does anyone have an answer? (btw, long = four bytes; char = 1 byte; in case thats platform specific) what i want to do can be understood from this: unsigned long thelong = 1002; char thechars[4]; //how do i do this? thechars = thelong //and this thelong = thechars //replace the equals signs with an explanation please! :-) thanks for all your help everyone -joe -- Posted via CNET Help.com http://www.*-*-*.com/
|
Mon, 26 Jan 2004 17:30:17 GMT |
|
 |
k.. #2 / 24
|
 Convert four chars to a long and a long to four chars
Quote: > if i have an array of four chars, how can i make it a long? > the reason i want to do it (transfering numbers on the net) is not c > related BUT MY QUESTION IS SO DONT "FLAME" ME
It's a C question, worry not. Quote: > (btw, long = four bytes; char = 1 byte; in case thats platform specific)
It is indeed. As is "chars have 8 bits", and "the lowest addressed char is the most significant part of the long". Quote: > what i want to do can be understood from this: > unsigned long thelong = 1002; > char thechars[4]; > //how do i do this? > thechars = thelong > //and this > thelong = thechars > //replace the equals signs with an explanation please! :-)
Bit by bit; or rather, byte by byte. #include <limits.h> unsigned long charsToLong( unsigned char *theChars ) { return ((unsigned long) theChars[0] << 24) | ((unsigned long) theChars[1] << 16) | ((unsigned long) theChars[2] << 8) | ((unsigned long) theChars[3]) ; } void longToChars( unsigned long it, unsigned char *theChars ) { theChars[0] = (it >> 24); theChars[1] = (it >> 16); theChars[2] = (it >> 8); theChars[3] = it; } EXERCISES. (a) bytes are CHAR_BITS wide [from limits.h]; revise the code so that the shifts take this into account. (b) longs need not be 4 bytes wide; revise the code to take this into account. Is a loop needed? How likely is it we can do without one? How good is your compiler at unrolling, and does it matter? (c) the author of this code makes no warrenty as to its effectiveness. Is his paranoia justified? -- Chris "electric hedgehog" Dollin C FAQs at: http://www.faqs.org/faqs/by-newsgroup/comp/comp.lang.c.html
|
Mon, 26 Jan 2004 18:04:04 GMT |
|
 |
Gergo Bara #3 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> if i have an array of four chars, how can i make it a long? > the reason i want to do it (transfering numbers on the net) is not c > related BUT MY QUESTION IS SO DONT "FLAME" ME > does anyone have an answer? > (btw, long = four bytes; char = 1 byte; in case thats platform specific)
sizeof (char) is always 1, but CHAR_BIT may be greater than 8. The long type must be at least 32 bits wide. Quote: > what i want to do can be understood from this: > unsigned long thelong = 1002; > char thechars[4];
Better make those unsigned chars. Quote: > //how do i do this? > thechars = thelong > //and this > thelong = thechars
You could try mempcy() or something similar, but you might run into endianness issues. You could build on this code: #include <stdio.h> #include <limits.h> int main(void) { unsigned long l, temp; unsigned char c[sizeof l]; size_t i; l = 0xabcdef01UL; printf("l: %lx\n", l); printf("c: "); for (i = 0; i < sizeof l; i++) { temp = l & ((unsigned long) UCHAR_MAX << CHAR_BIT * i); c[i] = temp >> (CHAR_BIT * i); printf("%02x ", (unsigned int) c[i]); } putchar('\n'); l = 0; for (i = 0; i < sizeof l; i++) { l |= c[i] << CHAR_BIT * i; } printf("l: %lx\n", l); return 0; Quote: }
HTH, Gergo -- QOTD: How can I miss you if you won't go away?
|
Mon, 26 Jan 2004 18:13:01 GMT |
|
 |
rand mair fhe #4 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
>if i have an array of four chars, how can i make it a long? >the reason i want to do it (transfering numbers on the net) is not c >related BUT MY QUESTION IS SO DONT "FLAME" ME >does anyone have an answer? >(btw, long = four bytes; char = 1 byte; in case thats platform specific) >what i want to do can be understood from this: >unsigned long thelong = 1002; >char thechars[4];
#include <limits.h> unsigned long strlong(char *s) { unsigned long r = 0; int i; unsigned chars *S = (unsigned char*)s; for (i=0; i<sizeof r && *S; i++) { r = (r<<CHAR_BIT) | *S++; } return r; } char *longstr(unsigned long l) { static char r[(sizeof l)+1]; char *R = r + (sizeof l)+1; *R-- = 0; while (R>r && l!=0) { *R-- = l; l >>= CHAR_BIT; } return R; } on irix and gnu compilers strlong("xyzq")=='xyzq' some compilers may reject multicharacter literals or store the bytes in a different order
|
Mon, 26 Jan 2004 18:11:38 GMT |
|
 |
pete #5 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> if i have an array of four chars, how can i make it a long? > the reason i want to do it (transfering numbers on the net) is not c > related BUT MY QUESTION IS SO DONT "FLAME" ME > does anyone have an answer? > (btw, long = four bytes; char = 1 byte; > in case thats platform specific)
It is platform specific. Quote: > what i want to do can be understood from this: > unsigned long thelong = 1002; > char thechars[4];
For starters, use unsigned char instead of char, whenever you're manipulating bytes and or bits. Quote: > //how do i do this? > thechars = thelong > //and this > thelong = thechars
Is the high byte of thelong, thechars[0] or thechars[3]? -- pete
|
Mon, 26 Jan 2004 18:09:02 GMT |
|
 |
Kalle Olavi Niemital #6 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> unsigned long thelong = 1002; > char thechars[4];
Make it an array of unsigned char. Quote: > //how do i do this? > thechars = thelong
thechars[0] = (thelong >> 24) & 0xFF; thechars[1] = (thelong >> 16) & 0xFF; thechars[2] = (thelong >> 8) & 0xFF; thechars[3] = (thelong >> 0) & 0xFF; Quote: > //and this > thelong = thechars
thelong = ((unsigned long) thechars[0] << 24) | ((unsigned long) thechars[1] << 16) | ((unsigned long) thechars[2] << 8) | ((unsigned long) thechars[3] << 0); These are portable ways to encode an at most 32-bit unsigned integer to big-endian format and decode it back. If the unsigned long type of some platform has more than 32 bits, these statements ignore the extras. Likewise, if unsigned char has more than 8 bits, these statements leave the extra bits zero. If you need little-endian format, swap the array indexes around.
|
Mon, 26 Jan 2004 18:04:17 GMT |
|
 |
Richard Heathfiel #7 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> if i have an array of four chars, how can i make it a long? > the reason i want to do it (transfering numbers on the net) is not c > related BUT MY QUESTION IS SO DONT "FLAME" ME > does anyone have an answer? > (btw, long = four bytes; char = 1 byte; in case thats platform specific)
It is indeed platform-specific. The only thing you are guaranteed is that chars are at least 8 bits but maybe more, and longs are at least 32 bits but maybe more. Furthermore, you should be aware that not all platforms use the same byte ordering: 16909060 (decimal) is represented by some platforms as 0x01020304 and by others as 0x04030201, and those aren't the only two possibilities! Quote: > what i want to do can be understood from this: > unsigned long thelong = 1002; > char thechars[4]; > //how do i do this? > thechars = thelong > //and this > thelong = thechars > //replace the equals signs with an explanation please! :-)
The easiest way is to cheat. That you are using unsigned long makes things easier. :-) But do make thechars unsigned as well: unsigned long thelong = 1002; unsigned char thechars[sizeof(long)] = {0}; /* = {0} zeroes out the array */ unsigned char *p, *q; size_t i; p = (unsigned char *)&thelong; q = thechars; for(i = 0; i < sizeof thelong; i++) { *q++ = *p++; Quote: }
but this solution does depend upon byte ordering. You can get byte-ordering-independent code fairly easily (or rather, you can normalise the byte ordering), simply by exploring each bit: #include <limits.h> int main(void) { unsigned long thelong = 1002; unsigned char thechars[sizeof(long)] = {0}; int bit = 0; while(thelong > 0) { thechars[bit / CHAR_BIT] |= ((thelong & 1) << (bit % CHAR_BIT)); thelong >>= 1; ++bit; } return 0; Quote: }
Not tested, or even compiled, so be wary of loop boundary condition bugs. If this gives you the bits in the opposite order to the one you prefer, simply change int bit = 0; to int bit = sizeof thelong, move ++bit to be the first statement in the loop, and change it to --bit. --
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton
|
Mon, 26 Jan 2004 18:36:20 GMT |
|
 |
k.. #8 / 24
|
 Convert four chars to a long and a long to four chars
I'm piggybacking, rather than responding to Richard. A bit of experimenting sugested this: static unsigned long charsToLong( unsigned char *them ) { register unsigned long result = 0; if (sizeof (unsigned long) > 0) result = (result << CHAR_BIT) | them[0]; if (sizeof (unsigned long) > 1) result = (result << CHAR_BIT) | them[1]; if (sizeof (unsigned long) > 2) result = (result << CHAR_BIT) | them[2]; if (sizeof (unsigned long) > 3) result = (result << CHAR_BIT) | them[3]; if (sizeof (unsigned long) > 4) result = (result << CHAR_BIT) | them[4]; if (sizeof (unsigned long) > 5) result = (result << CHAR_BIT) | them[5]; if (sizeof (unsigned long) > 6) result = (result << CHAR_BIT) | them[6]; if (sizeof (unsigned long) > 7) result = (result << CHAR_BIT) | them[7]; return result; } So long as sizeof(unsigned long) <= 8, which covers all the machines I dare think about, this does it portably and with no loops. If your compiler won't optimise away the sizeof tests, either turn up the optimisation level a tad or get a better compiler. Critiques requested. -- Chris "now, where's that mask ... and the cloak ... and the ring ..." Dollin C FAQs at: http://www.faqs.org/faqs/by-newsgroup/comp/comp.lang.c.html
|
Mon, 26 Jan 2004 19:19:34 GMT |
|
 |
Richard Heathfiel #9 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> I'm piggybacking, rather than responding to Richard. A bit of experimenting > sugested this: > static unsigned long charsToLong( unsigned char *them ) > { > register unsigned long result = 0; > if (sizeof (unsigned long) > 0) result = (result << CHAR_BIT) | them[0]; > if (sizeof (unsigned long) > 1) result = (result << CHAR_BIT) | them[1]; > if (sizeof (unsigned long) > 2) result = (result << CHAR_BIT) | them[2]; > if (sizeof (unsigned long) > 3) result = (result << CHAR_BIT) | them[3]; > if (sizeof (unsigned long) > 4) result = (result << CHAR_BIT) | them[4]; > if (sizeof (unsigned long) > 5) result = (result << CHAR_BIT) | them[5]; > if (sizeof (unsigned long) > 6) result = (result << CHAR_BIT) | them[6]; > if (sizeof (unsigned long) > 7) result = (result << CHAR_BIT) | them[7]; > return result; > } > So long as sizeof(unsigned long) <= 8, which covers all the machines I > dare think about, this does it portably and with no loops. If your compiler > won't optimise away the sizeof tests, either turn up the optimisation > level a tad or get a better compiler. > Critiques requested.
Adding a while loop after the last if could catch really humungous ul's, at the expense of one redundant test on the more 'normal' architectures. --
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton
|
Mon, 26 Jan 2004 19:50:55 GMT |
|
 |
k.. #10 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
>> I'm piggybacking, rather than responding to Richard. A bit of experimenting >> sugested this: >> static unsigned long charsToLong( unsigned char *them ) >> { >> register unsigned long result = 0; >> if (sizeof (unsigned long) > 0) result = (result << CHAR_BIT) | them[0]; >> if (sizeof (unsigned long) > 1) result = (result << CHAR_BIT) | them[1]; >> if (sizeof (unsigned long) > 2) result = (result << CHAR_BIT) | them[2]; >> if (sizeof (unsigned long) > 3) result = (result << CHAR_BIT) | them[3]; >> if (sizeof (unsigned long) > 4) result = (result << CHAR_BIT) | them[4]; >> if (sizeof (unsigned long) > 5) result = (result << CHAR_BIT) | them[5]; >> if (sizeof (unsigned long) > 6) result = (result << CHAR_BIT) | them[6]; >> if (sizeof (unsigned long) > 7) result = (result << CHAR_BIT) | them[7]; >> return result; >> } >> So long as sizeof(unsigned long) <= 8, which covers all the machines I >> dare think about, this does it portably and with no loops. If your compiler >> won't optimise away the sizeof tests, either turn up the optimisation >> level a tad or get a better compiler. >> Critiques requested. > Adding a while loop after the last if could catch really humungous ul's, > at the expense of one redundant test on the more 'normal' architectures.
Like: if (sizeof (unsigned long) > 8) { size_t count = sizeof (unsigned long) - 8; int index = 8; while (count--) result = (result << CHAR_BIT) | them[index++]; } ?? -- Chris "electric hedgehog" Dollin C FAQs at: http://www.faqs.org/faqs/by-newsgroup/comp/comp.lang.c.html
|
Mon, 26 Jan 2004 19:58:53 GMT |
|
 |
pete #11 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> Is the high byte of thelong, thechars[0] or thechars[3]?
If it doesn't matter (though I suspect it does) then this would be the fatsest way: /* BEGIN new.txt */ thelong = 0XAABBCCDD; The intial value of thelong is AABBCCDD *(long*)thechars = thelong; thechars[0] DD thechars[1] CC thechars[2] BB thechars[3] AA theotherlong = *(long*)thechars; The value of the other long is AABBCCDD /* END new.txt */ /* BEGIN new.c */ #include <stdio.h> #include <stdlib.h> #define thechars (tchars.tchar) int main(void) { long thelong, theotherlong; union{ long lin; unsigned char tchar[sizeof(long)]; }tchars; size_t index; char *fn = "new.txt"; FILE *fp = fopen(fn, "wt"); if(!fp){ fprintf(stderr, "fopen(%s) error\n", fn); exit(EXIT_FAILURE); } fprintf(fp, "/* BEGIN %s */\n\n", fn); thelong = 0XAABBCCDD; fprintf(fp, "thelong = 0XAABBCCDD;\n"); fprintf(fp, "The intial value of thelong is %X\n\n", thelong); *(long*)thechars = thelong; fprintf(fp, "*(long*)thechars = thelong;\n"); for (index = 0; index != sizeof(long); ++index) fprintf(fp, "thechars[%lu] %X\n", (unsigned long)index, thechars[index]); theotherlong = *(long*)thechars; fprintf(fp, "\ntheotherlong = *(long*)thechars;\n"); fprintf(fp, "The value of the other long is %X\n", theotherlong); fprintf(fp, "\n/* END %s */\n", fn); fclose(fp); return 0; Quote: }
/* btw, long = four bytes; char = 1 byte; in case thats platform specific) what i want to do can be understood from this: unsigned long thelong = 1002; char thechars[4]; //how do i do this? thechars = thelong //and this thelong = thechars //replace the equals signs with an explanation please! :-) thanks for all your help everyone -joe */ /* END new.c */ -- pete
|
Mon, 26 Jan 2004 20:22:58 GMT |
|
 |
Mathew Hendr #12 / 24
|
 Convert four chars to a long and a long to four chars
: static unsigned long charsToLong( unsigned char *them ) : { : register unsigned long result = 0; : if (sizeof (unsigned long) > 0) result = (result << CHAR_BIT) | them[0]; : if (sizeof (unsigned long) > 1) result = (result << CHAR_BIT) | them[1]; : if (sizeof (unsigned long) > 2) result = (result << CHAR_BIT) | them[2]; : if (sizeof (unsigned long) > 3) result = (result << CHAR_BIT) | them[3]; : if (sizeof (unsigned long) > 4) result = (result << CHAR_BIT) | them[4]; : if (sizeof (unsigned long) > 5) result = (result << CHAR_BIT) | them[5]; : if (sizeof (unsigned long) > 6) result = (result << CHAR_BIT) | them[6]; : if (sizeof (unsigned long) > 7) result = (result << CHAR_BIT) | them[7]; : return result; : } : : So long as sizeof(unsigned long) <= 8, which covers all the machines I : dare think about, this does it portably and with no loops. If your compiler : won't optimise away the sizeof tests, either turn up the optimisation : level a tad or get a better compiler. Well, if your compiler won't automatically unroll a loop with a small constant number of iterations, either turn up the optimisation level a tad or get a better compiler. :) D:\>type catol.c #include <limits.h> unsigned long catol(const unsigned char *bp) { int sz = sizeof(unsigned long); unsigned long ul = 0; do { ul = (ul << CHAR_BIT) | *bp++; } while (--sz); return ul; Quote: }
D:\>uname -a CYGWIN_NT-5.0 AVALON 1.3.2(0.39/3/2) 2001-05-20 23:28 i686 unknown D:\>gcc --version 3.0 D:\>gcc -O3 -fomit-frame-pointer -funroll-loops catol.c -S D:\>type catol.s .file "catol.c" .text .align 16 .globl _catol .def _catol; .scl 2; .type 32; .endef _catol: movl 4(%esp), %ecx movzbl (%ecx), %eax movzbl 1(%ecx), %edx sall $8, %eax orl %edx, %eax movzbl 2(%ecx), %edx sall $8, %eax orl %edx, %eax movzbl 3(%ecx), %edx sall $8, %eax orl %edx, %eax ret -- Mat.
|
Mon, 26 Jan 2004 21:04:55 GMT |
|
 |
Richard Heathfiel #13 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> >> Critiques requested. > > Adding a while loop after the last if could catch really humungous ul's, > > at the expense of one redundant test on the more 'normal' architectures. > Like: > if (sizeof (unsigned long) > 8) > { > size_t count = sizeof (unsigned long) - 8; > int index = 8; > while (count--) result = (result << CHAR_BIT) | them[index++]; > } > ??
Yes, exactly like that. :-) --
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999. C FAQ: http://www.eskimo.com/~scs/C-faq/top.html K&R answers, C books, etc: http://users.powernet.co.uk/eton
|
Mon, 26 Jan 2004 21:01:08 GMT |
|
 |
pete #14 / 24
|
 Convert four chars to a long and a long to four chars
Quote:
> long thelong, theotherlong; > fprintf(fp, "The intial value of thelong is %X\n\n", thelong); > fprintf(fp, "thechars[%lu] %X\n", > (unsigned long)index, thechars[index]); > fprintf(fp, "The value of the other long is %X\n", theotherlong);
For the benefit of fprintf, those lines should be changed to: long unsigned thelong, theotherlong; fprintf(fp, "The intial value of thelong is %lX\n\n", thelong); fprintf(fp, "thechars[%lu] %X\n", (long unsigned)index, (unsigned)thechars[index]); fprintf(fp, "The value of the other long is %lX\n", theotherlong); -- pete
|
Mon, 26 Jan 2004 21:02:39 GMT |
|
|
Page 1 of 2
|
[ 24 post ] |
|
Go to page:
[1]
[2] |
|