2013-05-04 62 views
3

我發現了下面的代碼,它能夠將int64_t轉換爲網絡字節順序。現在我需要相反的代碼,以便將網絡字節順序轉換回我的小端機器。代碼是這樣的。C++ htonll和back

int64_t decode(void* value){ 
    int64_t vv = *((int64_t*) value); 
    int num = 42; 
    if(*(char *)&num == 42) //test big/little endian 
     return (((uint64)htonl(vv)) << 32) + htonl(vv >> 32); 
    else 
     return vv; 
} 

非常感謝!

+0

只是做同樣的,但方向相反。 – 2013-05-04 14:28:17

+1

@JoachimPileborg:爲什麼不直接說「做相反的事情」?從邏輯意義上說,「相同但相反」到底是什麼? – 2013-05-04 14:31:15

+1

'int64_t vv = *((int64_t *)value-> first);'是sooooo錯誤的原因很多!即使編譯正確,這段代碼也不可能做你想要的* mixed endian *系統。只需使用'printf(「%lld」,...);'...... – Sebivor 2013-05-04 15:12:12

回答

4

代碼爲您htonll

#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl((x) >> 32)) 

翻轉字節首尾。如果您應用了兩次,它會將該值恢復到原始狀態。所以相同的功能可用於ntohll

+5

此代碼有缺陷。它適用於主機和網絡字節順序相反的情況,但在相同的情況下,它會翻轉高32位和低32位。謹防! – chacham15 2013-05-22 00:52:48

+2

那麼,當然,如果主機和網絡的字節順序相反,則只會調用此代碼;請注意,在OP的問題中明確測試了主機是小端。 – 2013-05-22 16:04:34

+3

我沒有說它是'htonll',我說它是'你的'htonll'「。 – 2013-05-22 17:36:15

0

以下是我將如何使用聯合使用它。移位方法也可以很好地工作,但恕我直言,要正確地處理一點點技巧。

#include<stdlib.h> 
#include<stdio.h> 

union MyUnion { 
    int64_t i64; 
    int32_t i32[2]; 
}; 

int64_t htonll(int64_t hostFormatInt64) 
{ 
    MyUnion u; 
    u.i64 = hostFormatInt64; 
    int32_t temp = u.i32[0]; 
    u.i32[0] = htonl(u.i32[1]); 
    u.i32[1] = htonl(temp); 
    return u.i64; 
} 

int64_t ntohll(int64_t networkFormatInt64) 
{ 
    MyUnion u; 
    u.i64 = networkFormatInt64; 
    int32_t temp = u.i32[0]; 
    u.i32[0] = ntohl(u.i32[1]); 
    u.i32[1] = ntohl(temp); 
    return u.i64; 
} 

void Test(int64_t i) 
{ 
    printf("Testing value %lli\n", i); 
    int64_t networkI = htonll(i); 
    printf(" Network format is %lli (0x%llx)\n", networkI, networkI); 
    int64_t hostAgainI = ntohll(networkI); 
    printf(" Back to host again %lli (0x%llx)\n", hostAgainI, hostAgainI); 
    if (hostAgainI != i) 
    { 
     printf("ERROR, we didn't get the original value back!\n"); 
     abort(); 
    } 
} 

int main() 
{ 
    // A quick unit test to make sure I didn't mess anything up :) 
    int64_t i = 0; 
    while(1) 
    { 
     Test(i); 
     Test(-i); 
     i += rand(); 
    } 
    return 0; 
} 
+2

此代碼調用未定義的行爲,但位移方法沒有。 – 2013-05-05 07:08:42

+2

其實,我略有過時。由於允許通過union訪問C99類型的雙關聯。 – 2013-05-05 12:26:30

1

htonl可以通過以下完成步驟

  • 如果其大端系統直接返回值。無需做任何轉換。如果它的litte endian系統,需要做下面的轉換。
  • 取LSB 32位並應用'htonl'並移位32次。
  • 以MSB 32位(通過將uint64_t值右移32次)並應用'htonl'
  • 現在對第2步和第3步中接收到的值應用位OR。

同樣爲ntohll

#define HTONLL(x) ((1==htonl(1)) ? (x) : (((uint64_t)htonl((x) & 0xFFFFFFFFUL)) << 32) | htonl((uint32_t)((x) >> 32))) 
#define NTOHLL(x) ((1==ntohl(1)) ? (x) : (((uint64_t)ntohl((x) & 0xFFFFFFFFUL)) << 32) | ntohl((uint32_t)((x) >> 32))) 
+0

你能解釋一下你的解決方案嗎? – 2017-11-19 19:55:05

+0

@QualityCatalyst:新增說明。 – rashok 2017-11-21 04:56:34