[英]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.