簡體   English   中英

整數到字節數組Little Endian,反之亦然

[英]Integer to byte array Little Endian and vice versa

我想要方法將整數轉換為字節數組(小端),並從字節數組(以小端方式編碼)轉換為C中的整數; 無論我們在LE還是BE機器上工作。

這些功能適合嗎?

void Int2ByteArrayLE(int x,unsigned char *byteArray)
{

  byteArray[0]=x;
  byteArray[1]=x>>8;
  byteArray[2]=x>>16;
  byteArray[3]=x>>24;
}


void ByteArrayLE2Int(unsigned char *byteArray, int*x)
{
  *x=byteArray[0] | (byteArray[1]<<8) | (byteArray[2]<<16) | (byteArray[3]<<24);
}

PS。 如果x是帶符號的,這也有效嗎?

您實際上想做的是在主機字節順序和網絡字節順序之間轉換。 而您需要的是功能htonlntohl

要將主機從網絡字節順序轉換為:

uint32_t n = (uint32_t)htonl((uint32_t)h);

而在相反的方向:

int h = (int)ntohl((uint32_t)n);

這些功能知道主機平台的字節順序。 因此,如果您在大型字節序計算機上執行代碼,則這些功能將不起作用。 但是在小端機器上,這些函數會反轉字節。

在注釋中,您暗示您的通信協議要求以小尾數字節順序傳遞信息。 這肯定是一個錯誤。 您應該遵循標准協議,並以網絡字節順序在網絡上傳輸數據。

如果您真的不能更改協議,並且希望通過電線獲得很少的字節序,則只需要一個memcpy 您的值已經是低位字節序,並且顯然反轉字節將無濟於事。

如果您發現自己在大型endian客戶端上使用,那么您現在當然需要反轉字節。 為此使用此功能:

uint32_t reverseBytes32(uint32_t v){
  return ((v & 0xFF) << 24) | ((v & 0xFF00) << 8) 
         | ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24);
}

您將需要使用強制類型轉換將帶符號的int解釋為無符號的uint32_t

您的代碼有一些問題:

  • 在具有16位int的系統上,代碼將不起作用。
  • 在99%的情況下,對有符號整數使用按位運算符毫無意義。 如果有符號整數包含負數,那么如果您左移,甚至會遇到不確定的行為。

因此,代碼通常是不可移植的。 您需要將代碼更改為以下內容:

#include <stdint.h>

void uint32_to_ByteArrayLE (uint32_t x, uint8_t* byteArray)
{
  // explicit casts will prevent implicit conversion warnings:
  byteArray[0] = (uint8_t)(x >>  0);
  byteArray[1] = (uint8_t)(x >>  8);
  byteArray[2] = (uint8_t)(x >> 16);
  byteArray[3] = (uint8_t)(x >> 24);
}


void ByteArrayLE_to_uint32 (const uint8_t* byteArray, uint32_t* x)
{
  /* casts -before- shifting are necessary to prevent integer promotion 
     and to make the code portable no matter integer size: */

  *x = (uint32_t)byteArray[0] <<  0 | 
       (uint32_t)byteArray[1] <<  8 | 
       (uint32_t)byteArray[2] << 16 | 
       (uint32_t)byteArray[3] << 24;
}

如果不在第二個函數中進行強制轉換,則移位將發生在int ,這不是您想要的。

讓我們看一下標准(5.8 Shift運算符):

“ E1 << E2 ...,如果E1具有帶符號類型且非負值,並且E1 * 2 ^ E2在結果類型中可表示,那么它就是結果值;否則,行為是不確定的。”

“ E1 >> E2的值,E1右移E2位位置。...如果E1具有帶符號類型和負值,則結果值由實現定義。”

因此,當x帶符號且為負數時,行為對於<<而言是未定義的,而對於>>而言是實現定義的。 通常,對於帶符號的x,如果只有x為非負數,則代碼將起作用。

雅。 它也將在帶符號整數上工作,因為此代碼與MSB的>>移位無關,與MSB的符號位擴展無關。 即符號位是否置位,將不會影響代碼,因為它只涉及按原樣處理X的32位。 只需存儲並檢索32位。 因此將不考慮MSB處>>所添加的位。 要了解考慮,
如果x是int x; //然后是帶符號整數

x = -1即11111111 11111111 11111111 11111111

的ByteArray [0] = X; 11111111 11111111 11111111 11111111
的ByteArray [1] = X >> 8; xxxxxxxx 11111111 11111111 11111111
的ByteArray [2] = X >> 16; xxxxxxxx xxxxxxxx 11111111 11111111
的ByteArray [3] = X >> 24; xxxxxxxx xxxxxxxx xxxxxxxx 11111111

>> xxxxxxxx xxxxxxxx xxxxxxxx所添加的位不會被存儲/使用,因此不會影響代碼。
因此,由移位運算符done or not進行符號位擴展將不會影響代碼,因為從以上示例可以清楚地看出,移位x插入的位不用於存儲。 因此,代碼可以成功將數字存儲為binartarray中的數字,並且可以檢索回int x

暫無
暫無

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

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