比特交换和指针

时间:2012-10-24 09:11:36

标签: c++ byte swap endianness

我有一个struct,它由多个32位元素组成。我应用了#pragma pack (4),因此以下结构是线性的并且是对齐的。

struct
{
  int a; // 4 bytes
  int b; // 4 bytes
  int c; // 4 bytes
} mystruct; // total 16 bytes

如何交换这些元素(小 - >大端)?

方法是void swap(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;
  }
}

5 个答案:

答案 0 :(得分:4)

您可以在不使用临时字符的情况下交换两个字节:

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;
    }
}

对于您的结构,您可以:

void endianSwap( mystruct & s )
{
     endianSwap( s.a );
     endianSwap( s.b );
     endianSwap( s.c );
}

当然,作为使用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 );
}

答案 1 :(得分:1)

这是您日常工作的可能修复

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;
  }
}

未经测试,但希望更接近正确。

答案 2 :(得分:0)

如果您使用的是基于* nix的计算机。有一些有用的功能可以做到:

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostint32);   // from host to network
                                      // means little to big if your machine is x86

答案 3 :(得分:0)

void swap(void* A, int b)
{
   //FIXME !
   int *c = (int*)A; // have to cast to an existing type. 'void' doesnt exist
   for (int i = 0; i < b; i+=4)  // we are flipping 4 bytes at a time
   {
        unsigned int a=*c;  // read the content, not the address
         // have to have unsigned, otherwise (a&0xff00ff00)>>8 extends the sign bit
        a = (a & 0x0000FFFF) << 16 | (a & 0xFFFF0000) >> 16;
        a = (a & 0x00FF00FF) << 8 | (a & 0xFF00FF00) >> 8;
        *c++= a;  // write back the content
   }
 }

无论如何:我喜欢用c或c语言进行字节交换的方法是通过副本: 这个概念比内置函数的名称更容易记住。

void swap(char *d, char *s, int N) { for (i=0;i<N;i++) d[i^3]=*s++;}

答案 4 :(得分:0)

我假设通过little-&gt; big endian你的意思是颠倒每个4字节元素中字节的顺序。我还假设通过“结构上的a空指针”,你的意思是“结构上的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;
  }
}