2010-11-13 124 views
4

我正在將一些C代碼轉換爲Delphi。有人可以向我解釋這條線的含義嗎?這行代碼是什麼意思?

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

下面是代碼的上下文的其餘部分:

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)); 
} 

在此先感謝 博揚

+3

你嘗試過這麼遠嗎?你堅持什麼?我們喜歡幫助自我幫助的人,而不僅僅是爲他們工作。 – Oded 2010-11-13 21:02:43

+0

好的。重述這個問題。有人可以向我解釋此行的含義nResult =((pBuffer [0] << 8)&0xFF00) | (pBuffer [1]&0x00FF); – 2010-11-13 21:11:47

+1

我厚引用的行是自我解釋。它從一個緩衝區元素獲取8位,然後從另一個緩衝區獲得8位,然後將它們連接在一起。 – Vovanium 2010-11-14 00:17:51

回答

4

顯然,(大寫所有這些定義使它很難讀)功能被調換佔用2或4字節的值的內部字節排序。例如:

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

我不知道如何把它們寫在Delphi ...

希望他們已經書面和Delphi使用了他們提供一些名稱或其他圖書館。檢查你的文檔。


編輯

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

在此行

pBuffer[0]是陣列pBuffer
pBuffer[0] << 8的第一元件被移位該值8位到左側(0×12變爲從0x1200)
(...) & 0xFF00是多餘的:它重置最右邊的8位

pBuffer[1] & 0x00FF只有最右邊的8個比特被保留(因此爲0x1234變得0x0034)

,其它的操作|是一個按位或

(... & 0xFF00) | (... & 0xFF00)是第一部分的最左邊的8位和最右邊的8個比特第二部分。


編輯:HTO */* TOH命名

htonlhtonsntohlntohs在C被用於主機和網絡字節順序之間值轉換的功能。

字節排序不一定是不同的(網絡字節順序是big-endian),所以功能的第一部分應該檢查主機字節順序在進行交換之前是小字節還是大字節序列...或者該檢查是在使用您發佈的功能的程序中完成的。

+0

謝謝你的回答。在調試c代碼和delphi代碼時,我得到了一些類似的結果:例如使用VC調試器的nIPOffset = UTIL_ntohs(64)顯示值16384.在delphi中使用ntohs(64)的結果相同。但是printf(「nIPOffset%d \ n」,nIPOffset);顯示20. – 2010-11-13 21:31:49

+0

nIPOffset = UTIL_ntohs(ip-> ip_off); //調試器顯示16384同樣是delphi結果 printf(「nIPOffset%d \ n」,nIPOffset); //屏幕上的結果是20.當我必須讀取新數據時,這是抵消的。數據長度大約爲40 – 2010-11-13 21:36:41

+0

在printf中使用「%d」會告訴printf使用參數中的「int」(通常是4個字節)。但nIPOffset似乎是「長」或「長」(8字節)。如果我的假設是正確的'printf'將忽略該值的4個字節。 – pmg 2010-11-13 21:41:28

3

您不必翻譯它們,只需包含WinSock,它包含所有四個!

2

這似乎只是一個字節的交換,你可以實現非常簡單:

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

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

有一個笨拙的標記*僅向後兼容* 16位字節轉換的內部'Swap()'過程(內聯,保存在CALL/RET)另外,什麼是常量說明符?你真的想要參數的bytewap **地址**嗎? – 2010-11-14 12:57:54

+0

不,我不想交換地址,常量只是因爲我們不需要複製 – Remko 2010-11-15 07:13:23

0

默默無聞的按位表達

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

意味着什麼:

var 
    pBuffer: PByteArray; 
    nResult: Word; 

如此,帕斯卡的結構清晰度如下:

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

即使字節交換隱正在這裏相當明顯