C++ 位交换和指针
我有一个C++ 位交换和指针,c++,byte,swap,endianness,C++,Byte,Swap,Endianness,我有一个结构,它由多个32位元素组成。我应用了一个#pragma包(4),因此下面的结构是线性和对齐的 struct { int a; // 4 bytes int b; // 4 bytes int c; // 4 bytes } mystruct; // total 16 bytes 如何交换这些元素(little->big endian) 方法是void交换(void*a,int-b),其中a指针指向结构,而b整数给出结构的大小 例如: void swap(void* a,
结构
,它由多个32位元素组成。我应用了一个#pragma包(4)
,因此下面的结构是线性和对齐的
struct
{
int a; // 4 bytes
int b; // 4 bytes
int c; // 4 bytes
} mystruct; // total 16 bytes
如何交换这些元素(little->big endian)
方法是void交换(void*a,int-b)
,其中a
指针指向结构,而b
整数给出结构的大小
例如:
void swap(void* a, int b)
{
//FIXME !
for (int i = 0; i < b; i+= 32)
{
a = (a & 0x0000FFFF) << 16 | (a & 0xFFFF0000) >> 16;
a = (a & 0x00FF00FF) << 8 | (a & 0xFF00FF00) >> 8;
a += 32;
}
}
void交换(void*a,int-b)
{
//修理我!
对于(int i=0;i16;
a=(a&0x00FF00FF)>8;
a+=32;
}
}
这里有一个可能的例程修复程序
void swap(void* a, int b)
{
for (int i = 0; i < b; i += 4)
{
int* p = (char*)a + i;
*p = (*p & 0x0000FFFF) << 16 | (*p & 0xFFFF0000) >> 16;
*p = (*p & 0x00FF00FF) << 8 | (*p & 0xFF00FF00) >> 8;
}
}
void交换(void*a,int-b)
{
对于(int i=0;i16;
*p=(*p&0x00FF00FF)>8;
}
}
未经测试,但希望更接近正确。如果您使用的是基于*nix的机器。有一个有用的函数可以做到这一点:
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostint32); // from host to network
// means little to big if your machine is x86
#包括
uint32_t htonl(uint32_t hostin32);//从主机到网络
//如果您的机器是x86,则表示从小到大
无效交换(无效*A,内部b)
{
//修理我!
int*c=(int*)A;//必须强制转换为现有类型。“void”不存在
对于(inti=0;i>8扩展符号位
a=(a&0x0000FFFF)>16;
a=(a&0x00FF00FF)>8;
*c++=a;//写回内容
}
}
无论如何:我最喜欢用c或c类语言进行字节交换的方法是通过拷贝:
这个概念比内置函数的名称更容易记住
void swap(char*d,char*s,int N){for(i=0;i您可以在不使用临时
void byteswap( unsigned char & a, unsigned char & b )
{
a ^= b;
b ^= a;
a ^= b;
}
现在,让我们将其应用于可变长度的数字
template< typename T >
void endianSwap( T & t )
{
unsigned char * first = reinterpret_cast< unsigned char * >( &t );
unsigned char * last = first + sizeof(T) - 1;
while( first < last )
{
byteswap( *first, *last );
++first;
--last;
}
}
当然,作为使用byteswap的endianSwap的替代方法,我们可以使用std::reverse
template<typename T> endianSwap( T& t )
{
unsigned char * begin = reinterpret_cast<unsigned char *>(&t);
unsigned char * end = begin + sizeof( T );
std::reverse( begin, end );
}
模板交换(T&T)
{
无符号字符*begin=重新解释强制转换(&t);
无符号字符*end=begin+sizeof(T);
标准::反向(开始、结束);
}
我假设little->big-endian是指颠倒每个4字节元素中字节的顺序。我还假设“a
null指针在结构上”是指“a
指针在结构上”。
您的代码中有一些错误。请尝试以下操作:
void swap(void* a, int b)
{
for (int *pInt = (int *)a; pInt < ((char *)a + b); pInt++)
{
*pInt = (*pInt & 0x0000FFFF) << 16 | (*pInt & 0xFFFF0000) >> 16;
*pInt = (*pInt & 0x00FF00FF) << 8 | (*pInt & 0xFF00FF00) >> 8;
}
}
void交换(void*a,int-b)
{
对于(int*pInt=(int*)a;pInt<((char*)a+b);pInt++)
{
*品脱=(*品脱和0x0000FFFF)>16;
*品脱=(*品脱和0x00FF00FF)>8;
}
}
元素d不是四个字节,而是一个字节。通过使用#pragma pack(4)
您已强制编译器在元素d之后添加三个填充字节,但您的代码访问这些字节仍然是一个错误。字符d[4]有什么问题吗
?@john post编辑,这不是我要找的。现在让我们假设结构仅由3个int组成。顺便说一句,您当前的pragma可能已经过时,因为一个满是int
s的结构至少与int
的对齐方式对齐,这很可能至少是4个字节。另一方面,我不明白您为什么要这样做让结构与16个字节对齐(除非您认为#pragma pack
考虑的是元素而不是字节,当然不是字节)。你的意思是字节交换而不是位交换。endian更改是字节交换,而不是位。@ChristianRau结构没有满int
,我清理了示例以使其更易于理解。当使用“对齐”时,我的意思是结构的元素在内存中相互跟随。这段代码假设大小b是以整数为单位的大小。可能是对的,但我认为更可能是以字节为单位的大小。如果你想交换到big-endian。但是如果你想从大到小交换,该函数将不起作用。那又怎样?还有ntohl
@Patouf Basi凯莉:是的。简而言之,还有另一个版本。是的,但是如果你在大端机平台上,换成小端机是不起作用的。当然,你可以用它作为小端机系统的实现。
template<typename T> endianSwap( T& t )
{
unsigned char * begin = reinterpret_cast<unsigned char *>(&t);
unsigned char * end = begin + sizeof( T );
std::reverse( begin, end );
}
void swap(void* a, int b)
{
for (int *pInt = (int *)a; pInt < ((char *)a + b); pInt++)
{
*pInt = (*pInt & 0x0000FFFF) << 16 | (*pInt & 0xFFFF0000) >> 16;
*pInt = (*pInt & 0x00FF00FF) << 8 | (*pInt & 0xFF00FF00) >> 8;
}
}