我目前正在用 C 撰寫一個二進制應用程式協議,該協議使用套接字在網路上發送 uint32_t 和雙打。在撰寫 uint32_t 時,我總是使用 htonl() 函式將主機位元組順序轉換為網路位元組順序。但是,雙打不存在這樣的功能。所以我最終撰寫了一個新函式來檢查主機位元組順序并在必要時反轉雙精度的位元組順序。
double netHostToNetFloat64(double input)
{
typedef union DoubleData
{
double d;
char c[8];
} DoubleData;
DoubleData input_data, output_data;
if(netHostIsBigEndian())
{
return input;
}
else
{
input_data.d = input;
output_data.c[0] = input_data.c[7];
output_data.c[1] = input_data.c[6];
output_data.c[2] = input_data.c[5];
output_data.c[3] = input_data.c[4];
output_data.c[4] = input_data.c[3];
output_data.c[5] = input_data.c[2];
output_data.c[6] = input_data.c[1];
output_data.c[7] = input_data.c[0];
return output_data.d;
}
}
但是,當網路對等方讀取雙精度時,我得到了一些奇怪的結果。我確信我的函式正在反轉位元組順序,但是,我很好奇存盤無效的雙精度值(即它導致 Inf 或 NaN)是否會在下次讀取時破壞輸出?
另外,我意識到顛倒位元組順序并將結果放回雙精度是愚蠢的,但是,我想使其與 htonl/htons/ntohl/ntohs 函式保持一致。
uj5u.com熱心網友回復:
我會使用其他方式來反轉價值。
uint64_t reversebytes(double d)
{
uint64_t u;
memcpy(&u, &d, sizeof(u));
u = (u >> 56) | (u << 56) |
((u & 0x00ff000000000000) >> 40) | ((u & 0x000000000000ff00) << 40) |
((u & 0x0000ff0000000000) >> 24) | ((u & 0x0000000000ff0000) << 24) |
((u & 0x000000ff00000000) >> 8) | ((u & 0x00000000ff000000) << 8) ;
return u;
}
編譯器對這段代碼進行了很好的優化:https ://godbolt.org/z/qn6ar3hvM
編譯器優化您的功能要困難得多:https ://godbolt.org/z/M4shPoEnE
uj5u.com熱心網友回復:
Double是八個位元組,所以你需要將值的八個位元組反轉才能在網路上發送它......通常,當你發送一個 IEEE-752 時,協議規范會指示必須先發送哪個位元組(它通常是最重要的值的位元組double,它具有符號和兩個指數的最高有效位元組。)但很常見(在英特爾架構中)將該位元組存盤在最后一個位元組中(再次類似于小端),所以你必須在傳輸之前將所有位元組順序更改為反向出現。其他架構我不確定它們是做什么的,但可能會做類似的事情。你可以使用這個:
uint64_t llhton(void *p)
{
uint64_t data = *(uint64_t *)p;
src = (data & 0xffffffff00000000) >> 32 | (data & 0x00000000ffffffff) << 32;
src = (data & 0xffff0000ffff0000) >> 16 | (data & 0x0000ffff0000ffff) << 16;
src = (data & 0xff00ff00ff00ff00) >> 8 | (data & 0x00ff00ff00ff00ff) << 8;
return data;
}
如果你有:
double value;
您可以將其序列化以輸出:
uint64_t data_in_network_order = llhton(&value);
whiledata_in_network_order是網路順序,在這個架構中沒有任何意義,所以為了方便,我使用了 64 位無符號資料,它應該被認為是不透明資料。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/416591.html
標籤:
