簡體   English   中英

如何重新排序整數的字節?

[英]How can I reorder the bytes of an integer?

我的任務是使用C將數據文件從big endian轉換為little endian,反之亦然。我已經在線查看了大約3個小時的其他示例和閱讀我的教科書,但是我很困惑甚至如何開始這個功能。

到目前為止,我的事件順序是正確的(1到4),但在我的convert_and_save函數中,我必須使用→ char buffer[4];創建一個char數組char buffer[4];

有人可以幫幫我嗎? 即使你只是給我一些關於查找內容的線索,我也會非常感激。

我需要編寫一個名為的函數:

void convert_and_save(struct record item, FILE * output_handle, int number);

在這個函數里面我做了以下一系列步驟:

  1. 使用以下方法將整數轉換為字符數組:

     int integer_to_characters(int number, char * buffer) { memcpy(buffer, &number, 4); } 
  2. 反轉該數組中字符的順序。

  3. 使用以下命令將字符數組轉換回整數:

     int characters_to_integer(char * buffer) { int result; memcpy(&result, buffer, 4); return result; } 
  4. 使用以下方法在輸出文件上寫入轉換后的記錄

     void save_record(FILE * file_handle, struct record a) { char output_buffer[size_of_record]; integer_to_characters(a.age, &(output_buffer[0])); memcpy(&(output_buffer[4]), a.name, 12); integer_to_characters(a.department, &(output_buffer[16])); fwrite(output_buffer, sizeof(char), size_of_record, file_handle); } 

這是我為Parrot VM編寫的一個函數,你可以從parrotcode.org下載byteorder.c。 可能有更短的方法,但這適用於不同大小的整數,我們有一個宏來檢測PARROT_BIGENDIAN平台的字節順序,你可以丟棄所有這些。 另外,如上所述,您可以搜索hintonl(),這是bigendian硬件上的nop,但轉換為小端(只需獲取Linux x86實現)

INTVAL
fetch_iv_le(INTVAL w)
{
    ASSERT_ARGS(fetch_iv_le)
#if !PARROT_BIGENDIAN
    return w; // No-op on little endian hardware
#else
#  if INTVAL_SIZE == 4
    return (w << 24) | ((w & 0xff00) << 8) | ((w & 0xff0000) >> 8) | (w >> 24);
#  else
#    if INTVAL_SIZE == 8
    INTVAL r;

    r = w << 56;
    r |= (w & 0xff00) << 40;
    r |= (w & 0xff0000) << 24;
    r |= (w & 0xff000000) << 8;
    r |= (w & 0xff00000000) >> 8;
    r |= (w & 0xff0000000000) >> 24;
    r |= (w & 0xff000000000000) >> 40;
    r |= (w & 0xff00000000000000) >> 56;
    return r;
#    endif
#  endif
#endif
}

這些不是標准功能(這些是gcc擴展),但您可以使用它們:

- 內置函數:uint16_t __builtin_bswap16(uint16_t x)返回x,字節順序顛倒; 例如,0xaabb變為0xbbaa。 這里的字節總是意味着8位。

- 內置函數:uint32_t __builtin_bswap32(uint32_t x)與__builtin_bswap16類似,但參數和返回類型為32位。

- 內置函數:uint64_t __builtin_bswap64(uint64_t x)與__builtin_bswap32類似,但參數和返回類型為64位。

如果您可以使用這些,很可能會為您的平台帶來更優化的代碼,如果沒有,干得好,提交補丁到gcc :)

Clang還有__builtin_bswap16() __builtin_bswap32() __builtin_bswap64()

視覺工作室

unsigned short _byteswap_ushort (
   unsigned short val
);
unsigned long _byteswap_ulong (
   unsigned long val
);
unsigned __int64 _byteswap_uint64 (
   unsigned __int64 val
);

ICC有_bswap16, _bswap and _bswap64 *需要進一步參考

看看這個答案: https//stackoverflow.com/a/105339/1461424

如果您使用的是Visual C ++,請執行以下操作:包含intrin.h並調用以下函數:

對於16位數字:

 unsigned short _byteswap_ushort(unsigned short value); 

對於32位數字:

 unsigned long _byteswap_ulong(unsigned long value); 

對於64位數字:

 unsigned __int64 _byteswap_uint64(unsigned __int64 value); 

不需要轉換8位數字(字符)。

此外,這些僅針對無符號值定義,它們也適用於有符號整數。

對於浮點數和雙精度數,它比普通整數更難,因為這些可能與否可能在主機中按字節順序排列。 您可以在big-endian機器上獲得little-endian浮點數,反之亦然。

其他編譯器也有類似的內在函數。

GCC為例,您可以直接致電:

  uint16_t __builtin_bswap16 (uint16_t x) uint32_t __builtin_bswap32 (uint32_t x) uint64_t __builtin_bswap64 (uint64_t x) 

這是我的樣本。 它會反轉整數的字節順序。 請注意,C未指定int的大小。 它可以是16,32,64 ...如果你想確保尺寸,使用(uint_16t,uint_32t,uint_64t),

void reverse_endianess(int* number)
{
    char byte_arr[8] = {0};
    int i;

    for (i=0; i < sizeof(int); i++) {
        byte_arr[i] = (*number & 0xFF);
        *number = *number >> 8;
    }

    *number = 0;

    for (i=0; i < sizeof(int); i++) {
        *number |=  byte_arr[i];
        *number = *number << 8;
    }
}

您可能需要查看此答案該答案顯示了如何轉換兩種方式,也使用不同的字節大小。 這是一種方法,但在鏈接的線程中討論了更有效的方法。

uint32_t num = 9;
uint32_t b0,b1,b2,b3,b4,b5,b6,b7;
uint32_t res = 0;

b0 = (num & 0xf) << 28;
b1 = (num & 0xf0) << 24;
b2 = (num & 0xf00) << 20;
b3 = (num & 0xf000) << 16;
b4 = (num & 0xf0000) << 12;
b5 = (num & 0xf00000) << 8;
b6 = (num & 0xf000000) << 4;
b7 = (num & 0xf0000000) << 4;

res = b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7;

printf("%d\n", res);

暫無
暫無

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

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