[comp.sys.amiga.programmer] 4 bytes to a long?

mrimages@beach.gal.utexas.edu (06/09/91)

	Is there a fast, simple way to convert 4 bytes into a long? I am
doing it presently this way, but it seems kind of kludgy:

union 	{
	long tlong;
	char tchar[4];
	} mytime;
 
for(i=0;i<4;i++)
	mytime.tchar[i]=block[i];
sprintf(tempstr,"%s",ctime(&mytime.tlong));

Any suggestions or is this the best I can do?

"If all you have is a hammer, please return it to the record store."

R. Luebbert = mrimages@beach.gal.utexas.edu (UT Medical Branch Galveston)

mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (06/10/91)

In article <451.28517f01@beach.gal.utexas.edu> mrimages@beach.gal.utexas.edu writes:

	   Is there a fast, simple way to convert 4 bytes into a long? I am
   doing it presently this way, but it seems kind of kludgy:

   union 	{
	   long tlong;
	   char tchar[4];
	   } mytime;

   for(i=0;i<4;i++)
	   mytime.tchar[i]=block[i];
   sprintf(tempstr,"%s",ctime(&mytime.tlong));

   Any suggestions or is this the best I can do?

It's not portable is one problem. Doing the conversion explicitly is
both portable, and seems a little cleaner:

sprintf(tempstr, "%s", ctime((((((block[3] << 8) + block[2]) << 8) +
					block[1]) << 8) + block[0]));

	<mike
--
That time we slept together				Mike Meyer
That's as far as it went				mwm@pa.dec.com
Yet though we're not quite lovers			decwrl!mwm
You're more than a friend

mrimages@beach.gal.utexas.edu (06/10/91)

Sorry, to be less ambiguous I am including some lines that were left out of
my original source example:

In article <451.28517f01@beach.gal.utexas.edu>, mrimages@beach.gal.utexas.edu writes:
> 
> 	Is there a fast, simple way to convert 4 bytes into a long? I am
> doing it presently this way, but it seems kind of kludgy:
 
union 	{
 	long tlong;
 	char tchar[4];
 	} mytime;
char block[232];
  
 for(i=0;i<4;i++)
 	mytime.tchar[i]=block[123+i];
 sprintf(tempstr,"%s",ctime(&mytime.tlong));
 
> Any suggestions or is this the best I can do?  I am not really concerned
about Big_endian/Little_endian differences.   This is an Amiga specific
program.

Thanks to all who have replied VIA mail to date to this question and also
to my begin 644 FILENAME query.
--- 

 "If all you have is a hammer, please return it to the record store."
 
 R. Luebbert = mrimages@beach.gal.utexas.edu (UT Medical Branch Galveston)
 
 

jleonard@pica.army.mil (06/10/91)

mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
       
		Is there a fast, simple way to convert 4 bytes into a long?
	
I use :

char ch[4];
long l;

memcpy( (char *)&l, ch, sizeof(long));

___________________________________________________________________________
|Jeff Leonard                              Usenet: jleonard@pica.army.mil |
|     My strength is as the strength of ten because my code is pure.      |
---------------------------------------------------------------------------

mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (06/11/91)

In article <55908@nigel.ee.udel.edu> jleonard@pica.army.mil writes:
>mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
>       
>		Is there a fast, simple way to convert 4 bytes into a long?
>	
>I use :
>
>char ch[4];
>long l;
>
>memcpy( (char *)&l, ch, sizeof(long));

If portability isn't a concern:

	ULONG	l;
	char	*ch = &l;

ch[0] is MSB of l, ch[3] is LSB.  This is dependant on byte order of ULONG.

--
****************************************************
* I want games that look like Shadow of the Beast  *
* but play like Leisure Suit Larry.                *
****************************************************

forgeas@swinjm.UUCP (Jean-Michel Forgeas) (06/11/91)

In article <55908@nigel.ee.udel.edu>, jleonard@pica.army.mil writes:

> mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
>               Is there a fast, simple way to convert 4 bytes into a long?
>
> I use :
>
> char ch[4];
> long l;
>
> memcpy( (char *)&l, ch, sizeof(long));

To convert four bytes into a long:
    l = *((long*) ch)
This will generate only one instruction:
    move.l _ch,_l
--
                                     \___/
Jean-Michel Forgeas                   \-/
cbmvax!cbmehq!cbmfra!swinjm!forgeas    |    The Software Winery
                                      -^-
                           And, where is the universe ?

johnhlee@CS.Cornell.EDU (John H. Lee) (06/12/91)

In article <mykes.3486@amiga0.SF-Bay.ORG> mykes@amiga0.SF-Bay.ORG (Mike Schwartz) writes:
>In article <55908@nigel.ee.udel.edu> jleonard@pica.army.mil writes:
>>mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
>>		Is there a fast, simple way to convert 4 bytes into a long?
>>	
>>I use :
>>
>>char ch[4];
>>long l;
>>
>>memcpy( (char *)&l, ch, sizeof(long));
>
>If portability isn't a concern:
>
>	ULONG	l;
>	char	*ch = &l;
>
>ch[0] is MSB of l, ch[3] is LSB.  This is dependant on byte order of ULONG.

A little clarification is in order.  When you obtain the 4 bytes in the
first place (from for instance, fgetc()), place in the sizeof(long)-byte
buffer pointed to by "ch".  You can then access the long through "l" without
copying.  However, if the 4 bytes are say, in the middle of some other
buffer, you must still do a copy of the sizeof(long) bytes to ensure they
end up properly long-word aligned.

-------------------------------------------------------------------------------
The DiskDoctor threatens the crew!  Next time on AmigaDos: The Next Generation.
	John Lee		Internet: johnhlee@cs.cornell.edu
The above opinions are those of the user, and not of this machine.

S_ASCHMIDT@iravcl.ira.uka.de (|S| Angela Schmidt) (06/12/91)

In <19488689.ARN0eac@swinjm.UUCP> forgeas@swinjm.UUCP writes:

> In article <55908@nigel.ee.udel.edu>, jleonard@pica.army.mil writes:
> 
> > mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
> >               Is there a fast, simple way to convert 4 bytes into a long?
> >
> > I use :
> >
> > char ch[4];
> > long l;
> >
> > memcpy( (char *)&l, ch, sizeof(long));
> 
> To convert four bytes into a long:
>     l = *((long*) ch)
> This will generate only one instruction:
>     move.l _ch,_l
> --

Oh no! Please don't do this!!!! What will happen if the field of characters
begins at an odd address? The 68020 and higher will do this. But all others
will crash. The chance that the machine survives is about 50% only. Please,
please don't use this conversion!!!

>                                      \___/
> Jean-Michel Forgeas                   \-/
> cbmvax!cbmehq!cbmfra!swinjm!forgeas    |    The Software Winery
>                                       -^-
>                            And, where is the universe ?

---------------------------------------------------------+---------------------
Angela Schmidt   Internet: S_ASchmidt@iravcl.ira.uka.de  |        //
(Nessy in IRC)   BITNET:   UK8B@DKAUNI2.BITNET           | Amiga //
                 Phone:    +49 731 712316 & 721 6904-263 |   \\ // only 1000
                           MEZ: (10am-9pm)  (12pm-10pm)  |    \X/ the real one!
---------------------------------------------------------+---------------------

dix@clinet.fi (Risto Kaivola) (06/13/91)

S_ASCHMIDT@iravcl.ira.uka.de (|S| Angela Schmidt) writes:

>In <19488689.ARN0eac@swinjm.UUCP> forgeas@swinjm.UUCP writes:

>> In article <55908@nigel.ee.udel.edu>, jleonard@pica.army.mil writes:
>> 
>> > mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
>> >               Is there a fast, simple way to convert 4 bytes into a long?
>> >
>> > I use :
>> >
>> > char ch[4];
>> > long l;
>> >
>> > memcpy( (char *)&l, ch, sizeof(long));
>> 
>> To convert four bytes into a long:
>>     l = *((long*) ch)
>> This will generate only one instruction:
>>     move.l _ch,_l
>> --

>Oh no! Please don't do this!!!! What will happen if the field of characters
>begins at an odd address? The 68020 and higher will do this. But all others
>will crash. The chance that the machine survives is about 50% only. Please,
>please don't use this conversion!!!

I was just wondering, but shouldn't a correct 68000 C compiler generate
non-breaking code even in this case? It seems to me that there is just
a character pointer to long pointer conversion going on here, which, if
I know anything about standard C, should be perfectly legal. That is, in
case a data object starts at an odd address, and this object is to be
accessed by means of a long pointer, a standard C compiler that is in an
environment which doesn't let the processor do long integer access at an
odd address, should generate code that accesses the element by means of
two or more accesses to smaller entities. No? Does the ANSI standard state
that this is implementation-defined, then?

>>                                      \___/
>> Jean-Michel Forgeas                   \-/
>> cbmvax!cbmehq!cbmfra!swinjm!forgeas    |    The Software Winery
>>                                       -^-
>>                            And, where is the universe ?

>---------------------------------------------------------+---------------------
>Angela Schmidt   Internet: S_ASchmidt@iravcl.ira.uka.de  |        //
>(Nessy in IRC)   BITNET:   UK8B@DKAUNI2.BITNET           | Amiga //
>                 Phone:    +49 731 712316 & 721 6904-263 |   \\ // only 1000
>                           MEZ: (10am-9pm)  (12pm-10pm)  |    \X/ the real one!
>---------------------------------------------------------+---------------------
-- 
Risto Kaivola (dix@clinet.fi) or (Risto.Kaivola@f123.n220.z2.FIDONET.ORG)

carolyn@cbmvax.commodore.com (Carolyn Scheppner - CATS) (06/13/91)

In article <451.28517f01@beach.gal.utexas.edu> mrimages@beach.gal.utexas.edu writes:
>
>	Is there a fast, simple way to convert 4 bytes into a long?

The IFF code has always done it this way:

#define MAKE_ID(a,b,c,d)        \
        ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

where a,b,c,and d are characters and the result is a long
-- 
==========================================================================
 Carolyn Scheppner -- Tech. Mgr. CATS - Commodore Amiga Technical Support
 PHONE 215-431-9180 {uunet,rutgers}!cbmvax!carolyn  carolyn@commodore.com

 Calm down.  It's just ones and zeros.
==========================================================================

mbs@turing.acs.virginia.edu (Michael B. Smith) (06/14/91)

In article <22408@cbmvax.commodore.com> carolyn@cbmvax.commodore.com (Carolyn Scheppner - CATS) writes:
>In article <451.28517f01@beach.gal.utexas.edu> mrimages@beach.gal.utexas.edu writes:
>>
>>	Is there a fast, simple way to convert 4 bytes into a long?
>
>The IFF code has always done it this way:
>
>#define MAKE_ID(a,b,c,d)        \
>        ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))
>
>where a,b,c,and d are characters and the result is a long
>-- 
>==========================================================================
B
> Carolyn Scheppner -- Tech. Mgr. CATS - Commodore Amiga Technical Support
> PHONE 215-431-9180 {uunet,rutgers}!cbmvax!carolyn  carolyn@commodore.com
>
> Calm down.  It's just ones and zeros.
>==========================================================================

I use code similar to this, but have found that when a, b, c, & d are pointers
that the lower 8 bits need to be masked. My example is the following code
fragment:  

long make_long (p)
char
	*p;
{
	return ( ((*(p + 0) & 0xff)<<24) +
		 ((*(p + 1) & 0xff)<<16) +
		 ((*(p + 2) & 0xff)<<8 ) +
		 ((*(p + 3) & 0xff)    )  );
}

I've always presumed (but never checked) that the compiler optmizes out the
+0 construct (there for readability). I use this when I am reconstructing
a file that I don't have a 'struct' for. And of course (since I'm new to this),
this code could be buggy (especially since I don't do the casts) -- but it
works for me.:)

Michael B. Smith
mbs@turing.acs.virginia.edu

crash@ckctpa.UUCP (Frank J. Edwards) (06/14/91)

In article <19488689.ARN0eac@swinjm.UUCP> forgeas@swinjm.UUCP (Jean-Michel Forgeas) writes:
>In article <55908@nigel.ee.udel.edu>, jleonard@pica.army.mil writes:
>> mrimages@beach.gal.utexas.edu in <451.28517f01@beach.gal.utexas.edu> write:
>>               Is there a fast, simple way to convert 4 bytes into a long?
>> I use :
>> char ch[4];
>> long l;
>> memcpy( (char *)&l, ch, sizeof(long));
>
>To convert four bytes into a long:
>    l = *((long*) ch)
>This will generate only one instruction:
>    move.l _ch,_l

Yes, but watch out for alignment restrictions.  To take care of
that, put the "long l" before the "char ch".  On stack-oriented
machines, *usually* the long will be allocated on the stack first
and then the char array, so the array must be properly aligned.

A better method, though, is to use a union:

	union {
		char ch[4];
		long l;
	} uvar;

Now, put the individual bytes into uvar.ch[0] through uvar.ch[3] and
then read'em back as uvar.l

>Jean-Michel Forgeas
-- 
Frank J. Edwards		|  "I did make up my own mind -- there
2677 Arjay Court		|   simply WASN'T ANY OTHER choice!"
Palm Harbor, FL  34684-4504	|		-- Me
Phone (813) 786-3675 (voice)	|    Only Amiga Makes It Possible...