簡體   English   中英

C-無法將無符號char數組轉換為double

[英]C - fail to convert unsigned char array to double

我想在C中將無符號char數組轉換為double。我嘗試了很多方法,但是仍然錯誤地轉換為0.00000。

union {
   double longtitude;
   unsigned char bytes[sizeof(double)];
}u;
unsigned char * receive_buffer = malloc(65536);
int recv = recv(fd,receive_buffer,65536,0); 
// the buffer should has 8 byte value  {40 5c 80 23 8d a3 c2 12}

memcpy(&u.bytes,receive_buffer,sizeof(double));  // copy to char array
for ( int i=8;i>=0;i--){
        u.longtitude = u.bytes[i]; 
    }
printf("%lf",u.longtitude);  // the result is 0.000000 / the expected result should be 114.00217

我從互聯網上找到的上述代碼得到了“ 0.000000”的結果。 如何將char數組轉換為double? 上面的代碼有什么問題?

UPDATE

我在上面添加了更具體的代碼。 我已經檢查了receive_buffer的內容,它包含上述注釋中的值。 u.bytes可以通過memcpy從緩沖區正確獲取一個值。 union and for loop部分是我從其他類似問題中發現的方式。 我嘗試過,但結果= 0.000000。 抱歉,以前發布的代碼不明確,之前提到的問題; 我是C語言的新手。

刪除for循環。

memcpy將緩沖區中的bytes復制到聯合的bytes數組中。 這些字節與longitude成員使用的字節相同,因此它們已經就位。 您不需要for循環來復制這些字節,並且它錯誤地將字節的寫入double的 ,而不是寫入表示該值的字節。 同樣,循環索引是錯誤的,因為它在第一次迭代中使用8,但是將8字節對象中的字節索引為0到7。

不僅如此,在C語言中,您可以使用union或memcpy修改表示對象的字節。 您不需要兩者。 recv ,滿足:

double longitude;
memcpy(&longitude, receive_buffer, sizeof longitude);

我希望,你甚至可以做recv直接進入&longitude

完全刪除for循環。 我不確定您打算在那里使用它的意圖是什么,但是它會使您剛剛做的工作無法(或者更像是bb語)。

根據您的更新和114.00217 ,問題是字節順序。 無論您要從中獲得價值的任何機器,都沒有與您的機器相同的耐久性。 因此,在轉換為兩倍后,交換極性。

// endian_swap() function taken from https://stackoverflow.com/a/21507710/669576
// I modified to work with double
double endian_swap(double d)
{
    long x = *(long *)&d;
    x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
    x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
    x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;

    return *(double *)&x;
}

int main(void) {
    unsigned char s[] = {0x40,0x5c,0x80,0x23,0x8d,0xa3,0xc2,0x12};
    double d;
    // Just copy - no union needed
    memcpy(&d, s, sizeof(d));
    // Swap endianess
    d = endian_swap(d);
    printf("%lf\n", d);
    return 0;
}

輸出:114.002170

我沒有做很多網絡編程,但是我相信ntohl()函數用於此目的。 但是,我不知道是否有64位版本。


更新:另外,您可以使用htobe64() (感謝@Stargateur):

#include <endian.h>

int main(void) {
    unsigned char s[] = {0x40,0x5c,0x80,0x23,0x8d,0xa3,0xc2,0x12};
    // htobe64() expects a long, so use that first
    long l;
    memcpy(&l, s, sizeof(l));
    l = htobe64(l);
    // Then copy the swapped long bits to a double
    double d;
    memcpy(&d, &l, sizeof(d));
    printf("%lf\n", d);
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM