gpt4 book ai didi

c++ - 使用宏将不带零位的C++反转4个字节的字节顺序

转载 作者:行者123 更新时间:2023-12-01 14:57:52 27 4
gpt4 key购买 nike

我几乎已经弄清楚了,但是我有一个简单的问题。下面的代码反转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);

因为 xunsigned 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 swap algorithm交换字节(从第一个+最后一个开始,向中间移动)。我们可以使用一个临时变量将其重写以执行相同的操作,但是可以提高可读性:
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。即使您不更改宏,这也将导致仅交换两个字节。您还可以使用强制转换或修改宏以接受自定义大小来实现相同目的。

关于c++ - 使用宏将不带零位的C++反转4个字节的字节顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60963910/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com