[英]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);
在這個函數里面我做了以下一系列步驟:
使用以下方法將整數轉換為字符數組:
int integer_to_characters(int number, char * buffer) { memcpy(buffer, &number, 4); }
反轉該數組中字符的順序。
使用以下命令將字符數組轉換回整數:
int characters_to_integer(char * buffer) { int result; memcpy(&result, buffer, 4); return result; }
使用以下方法在輸出文件上寫入轉換后的記錄
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.