bojan gavrilovic
bojan gavrilovic

Reputation: 167

What does this line of C code mean?

I'm converting some C code to Delphi. Can someone please explain to me what this line means?

nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00 )
 | ( pBuffer[ 1 ] & 0x00FF );

Here is the rest of the code for context:

USHORT UTIL_htons( USHORT hostshort )
{
 PUCHAR pBuffer;
 USHORT nResult;

 nResult = 0;
 pBuffer = (PUCHAR )&hostshort;

 nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00 )
  | ( pBuffer[ 1 ] & 0x00FF );

 return( nResult );
}

USHORT UTIL_ntohs( USHORT netshort )
{
 return( UTIL_htons( netshort ) );
}
ULONG UTIL_htonl( ULONG hostlong )
{
 PUCHAR pBuffer;
 ULONG nResult;
 UCHAR c, *pResult;

 pBuffer = (PUCHAR )&hostlong;

 if( !pBuffer )
 {
  return( 0L );
 }

 pResult = (UCHAR * )&nResult;

 c = ((UCHAR * )pBuffer)[ 0 ];
 ((UCHAR * )pResult)[ 0 ] = ((UCHAR * )pBuffer)[ 3 ];
 ((UCHAR * )pResult)[ 3 ] = c;

 c = ((UCHAR * )pBuffer)[ 1 ];
 ((UCHAR * )pResult)[ 1 ] = ((UCHAR * )pBuffer)[ 2 ];
 ((UCHAR * )pResult)[ 2 ] = c;

 return( nResult );
}
ULONG UTIL_ntohl( ULONG netlong )
{
 return( UTIL_htonl( netlong ) );
}

Thanks in advance Bojan

Upvotes: 4

Views: 6234

Answers (4)

Free Consulting
Free Consulting

Reputation: 4402

rather obscure bitwise expression

nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00 )
 | ( pBuffer[ 1 ] & 0x00FF );

implies what:

var 
  pBuffer: PByteArray; 
  nResult: Word;

so, Pascal's structured clarity would look like:

WordRec(nResult).Hi := pBuffer^[0];
WordRec(nResult).Lo := pBuffer^[1];

even implicit byteswap is being pretty obvious here

Upvotes: 0

Jens M&#252;hlenhoff
Jens M&#252;hlenhoff

Reputation: 14873

You do not have to translate them, just include WinSock, it has all four of them!

Upvotes: 3

Remko
Remko

Reputation: 7340

It seems to be just a swap of bytes which you can implement very simply:

function Swap32(const Value: DWORD): DWORD; assembler;
asm
  bswap eax;
end;

function Swap16(const Value: WORD): WORD; assembler;
asm
  xchg al, ah;
end;

Upvotes: 2

pmg
pmg

Reputation: 108938

Apparently (all those defines in uppercase make it hard reading) the functions are swapping the internal byte ordering of values that occupy 2 or 4 bytes. For example:

UTIL_htons(0x1234); /* returns 0x3412 */
UTIL_htonl(0x12345678); /* returns 0x78563412 */

I have no idea how to write them in Delphi ...

Hopefully they are already written and the library Delphi uses has them with some name or other. Check your documentation.


Edit

nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00 ) | ( pBuffer[ 1 ] & 0x00FF );

in this line

pBuffer[0] is the first element of the array pBuffer
pBuffer[0] << 8 is shifting that value 8 bits to the left (0x12 becomes 0x1200)
(...) & 0xFF00 is redundant: it resets the rightmost 8 bits

In pBuffer[1] & 0x00FF only the rightmost 8 bits are kept (so 0x1234 becomes 0x0034)

The other operation | is a bitwise or

( ... & 0xFF00) | ( ... & 0xFF00) is the leftmost 8 bits of the first part and the rightmost 8 bits of the second part.


Edit: hto* / *toh naming

The functions htonl, htons, ntohl, ntohs in C are used to convert values between host and network byte order.

The byte ordering is not necessarily different (network byte order is big-endian), so the first part of the functions should check if the host byte ordering is little- or big-endian before doing the swaps ... or the check was done previously in the program that uses the functions you posted.

Upvotes: 4

Related Questions