[英]Reversing the byte order of 4 bytes without the Zeros C++ Using a macro
我幾乎已經弄清楚了,但我有一個簡單的問題。 下面的代碼反轉 2 個字節的字節順序並打印以下內容,但"CDAB"
后面有 12 個零。
我不確定如何更改代碼,因此它只反轉 2 個字節而沒有額外的零。 宏超出我的范圍......它與int
類型的大小有關嗎?
電流輸出:
Your Computer uses Little-Endian
Before: ABCD
After : CDAB000000000000
我目前的代碼:
// Writing Data to A file.
#include <iostream>
#include <math.h>
using namespace std;
//The below code is used to reverse byte/Endian order.
#define REVERSE_BYTES(...) do for(size_t REVERSE_BYTES=0; REVERSE_BYTES<sizeof(__VA_ARGS__)>>1; ++REVERSE_BYTES)\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES];\
while(0)
// Check for Endianess
int Endianess(int y)
{
int num = 1;
if (static_cast<unsigned char>(num) == 1)
{
y = 1; // Little Endian
}
else
{
y = 0; // Big Endian
}
return y;
}
int Reverse_Endian(unsigned long long Reverse_Byte_Order)
{
//unsigned long long x = 0xABCDEF0123456789;
unsigned long long x = 0xABCD;
printf("\nBefore: %llX\n", x);
REVERSE_BYTES(x);
printf("After : %llX\n", x);
return x;
}
int main()
{
int x = 0;
x = Endianess(x);
if (x == 0)
{
cout << "Your Computer uses Big-Endian";
}
else
{
cout << "Your Computer uses Little-Endian ";
}
Reverse_Endian(x);
return 0;
}
盡管您將0xABCD
分配給x
,但這不會使x
成為兩字節整數。 整數的大小由它的類型unsigned long long
(通常為 64 位/8 字節)決定。
因此,盡管分配后x
的數值是0xABCD
,但它仍然由 8 字節的內存表示(可視化為0x000000000000ABCD
)。
由於技術原因, printf
需要知道變量類型/大小,但仍然只打印數值(僅按要求添加前導零)。 printf
本身不會“十六進制轉儲”任意變量。
預處理器宏只是執行文本替換。 手動執行此替換可以幫助了解發生了什么。 從原文開始:
#define REVERSE_BYTES(...) do for(size_t REVERSE_BYTES=0; REVERSE_BYTES<sizeof(__VA_ARGS__)>>1; ++REVERSE_BYTES)\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES];\
while(0);
你的REVERSE_BYTES(x);
語句被宏替換。 __VA_ARGS__
被宏參數替換:
do for(size_t REVERSE_BYTES=0; REVERSE_BYTES<sizeof(x)>>1; ++REVERSE_BYTES)
((unsigned char*)&(x))[REVERSE_BYTES] ^= ((unsigned char*)&(x))[sizeof(x)-1-REVERSE_BYTES],
((unsigned char*)&(x))[sizeof(x)-1-REVERSE_BYTES] ^= ((unsigned char*)&(x))[REVERSE_BYTES],
((unsigned char*)&(x))[REVERSE_BYTES] ^= ((unsigned char*)&(x))[sizeof(x)-1-REVERSE_BYTES];
while(0);
因為x
是一個unsigned long long
,我們假設它在你的機器上是 8 個字節。 sizeof(x)
應該等於 8。
do for(size_t REVERSE_BYTES=0; REVERSE_BYTES < 4; ++REVERSE_BYTES)
((unsigned char*)&(x))[REVERSE_BYTES] ^= ((unsigned char*)&(x))[7-REVERSE_BYTES],
((unsigned char*)&(x))[7-REVERSE_BYTES] ^= ((unsigned char*)&(x))[REVERSE_BYTES],
((unsigned char*)&(x))[REVERSE_BYTES] ^= ((unsigned char*)&(x))[7-REVERSE_BYTES];
while(0);
for 語句被包裝在一個冗余的 do-while 循環中,並且只包含一個語句。 更改這些宏特性以使其適合您的代碼風格:
for(size_t i=0; i<4; ++i) {
((unsigned char*)&(x))[i] ^= ((unsigned char*)&(x))[7-i];
((unsigned char*)&(x))[7-i] ^= ((unsigned char*)&(x))[i];
((unsigned char*)&(x))[i] ^= ((unsigned char*)&(x))[7-i];
}
這個宏使用XOR 交換算法來交換字節(從第一個+最后一個開始,向中間移動)。 我們可以使用臨時變量重寫它來做同樣的事情,但提高可讀性:
for(size_t i=0; i<4; ++i) {
unsigned char tmp = ((unsigned char*)&(x))[7-i];
((unsigned char*)&(x))[7-i] = ((unsigned char*)&(x))[i];
((unsigned char*)&(x))[i] = tmp;
}
希望這能更好地展示宏實際上在做什么。 正如我們所見,4 和 7 控制交換的字節數。 這些來自sizeof(x)
。 所以如果我們想交換更少的字節,我們只需要縮小sizeof(x)
。
將unsigned long long x = 0xABCD
更改為unsigned short x = 0xABCD
將使sizeof(x) == 2
。 即使您保持宏不變,這也應該只交換兩個字節。 您還可以使用強制轉換或修改宏來接受自定義大小以實現相同的目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.