2

我有一个struct,它由多个 32 位元素组成。我应用了 a #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;
  }
}
4

5 回答 5

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 );
}
于 2012-10-24T09:30:03.603 回答
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;
  }
}

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

于 2012-10-24T09:20:56.053 回答
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
于 2012-10-24T09:21:55.773 回答
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++;}

于 2012-10-24T09:21:56.880 回答
0

我假设 little->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;
  }
}
于 2012-10-24T09:32:18.137 回答