2

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

5 に答える 5

4

一時的なものを使用せずに2バイトを交換できます。

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

リトル->ビッグエンディアンとは、各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;
  }
}
于 2012-10-24T09:32:18.137 に答える