-4

次の構造体を使用します。

public struct ION
{
    public Single a0;
    public Single a1;
    public Single a2;
    public Single a3;
    public Single b0;
    public Single b1;
    public Single b2;
    public Single b3;
    public Double A1;
    public Double A0;
    public UInt32 Tot;
    public Int16 Wnt;
    public Int16 DtLS;
    public Int16 WnLSF;
    public Int16 DN;
    public Int16 DtLSF;
    public Int16 Wn;
    public UInt32 Tow;
    public Int16 bulwn;
    public UInt32 bultow;
    public UInt16 checksum;
}

...「構造を37の符号なしショートに分割し、それらを足し合わせ、結果の最下位16ビットを取得することによって計算される」場合、チェックサム値をどのように計算しますか?

4

2 に答える 2

2

まず、構造体からバイト配列を作成し (こちらを参照)、値BitConvert.ToUInt16()を読み取ってushortそこから追加します。

于 2012-12-14T19:55:08.560 に答える
1

これがそれを行う1つの方法ですが、それが要件を満たすかどうかはわかりません. CPUエンディアンは重要ですか?

public struct ION
{
    public Single a0    ;
    public Single a1    ;
    public Single a2    ;
    public Single a3    ;
    public Single b0    ;
    public Single b1    ;
    public Single b2    ;
    public Single b3    ;
    public Double A1    ;
    public Double A0    ;
    public UInt32 Tot   ;
    public Int16  Wnt   ;
    public Int16  DtLS  ;
    public Int16  WnLSF ;
    public Int16  DN    ;
    public Int16  DtLSF ;
    public Int16  Wn    ;
    public UInt32 Tow   ;
    public Int16  bulwn ;
    public UInt32 bultow ;

    public UInt16 checksum
    {
        get
        {
            byte[][] raw =
            {
                BitConverter.GetBytes( a0     ) ,
                BitConverter.GetBytes( a1     ) ,
                BitConverter.GetBytes( a2     ) ,
                BitConverter.GetBytes( a3     ) ,
                BitConverter.GetBytes( b0     ) ,
                BitConverter.GetBytes( b1     ) ,
                BitConverter.GetBytes( b2     ) ,
                BitConverter.GetBytes( b3     ) ,
                BitConverter.GetBytes( A1     ) ,
                BitConverter.GetBytes( A0     ) ,
                BitConverter.GetBytes( Tot    ) ,
                BitConverter.GetBytes( Wnt    ) ,
                BitConverter.GetBytes( DtLS   ) ,
                BitConverter.GetBytes( WnLSF  ) ,
                BitConverter.GetBytes( DN     ) ,
                BitConverter.GetBytes( DtLSF  ) ,
                BitConverter.GetBytes( Wn     ) ,
                BitConverter.GetBytes( Tow    ) ,
                BitConverter.GetBytes( bulwn  ) ,
                BitConverter.GetBytes( bultow ) ,
            } ;
            byte[] cooked = raw.SelectMany( x => x ).ToArray() ;
            uint  accumulator = 0 ;

            for ( int i = 0 ; i < cooked.Length ; i+= 2 )
            {
                ushort value = BitConverter.ToUInt16( cooked , i ) ;
                accumulator += value ;
            }
            return (ushort) accumulator ;
        }
    }

}

または、安全でないコードにドロップダウンして、次のようにすることもできます。

public UInt16 checksum
{
  get
  {
    uint accumulator = 0 ;
    unsafe
    {
      fixed ( ION* x = &this )
      {
        for ( ushort *p = (ushort*) x ; p < x+1 ; ++p )
        {
          accumulator += *p ;
        }
      }
    }
    return (ushort) accumulator ;
  }
}

しかし、構造内または構造の最後にパディングがある場合、パディング オクテットがゼロになることが保証されているとは思えないため、結果に影響が生じる可能性があります。また、構造体に奇数のオクテットが含まれている場合、構造体の最後を超えて読み取ろうとして例外をスローする可能性があります...または間違った値を計算します。

もちろん、構造体をメモリ ストリームにシリアル化し、それを ushort のストリームとして読み取ることもできます。

public UInt16 checksum
{
  get
  {
    uint accumulator = 0 ;
    using ( BinaryReader reader = new BinaryReader( new MemoryStream() ) )
    {
      BinaryFormatter bf = new BinaryFormatter();
      bf.Serialize( reader.BaseStream , this ) ;
      reader.BaseStream.Seek(0,SeekOrigin.Begin) ;
      while ( reader.BaseStream.Position < reader.BaseStream.Length )
      {
        ushort value = reader.ReadUInt16() ;
        accumulator += value ;
      }
    }
    return (ushort) accumulator ;
  }
}

しかし、繰り返しになりますが、これはレイアウト、エンディアン、およびパディングに関する仮定です。また、構造体のサイズが奇数の場合は、ほぼ確実に例外をスローします。

于 2012-12-14T21:16:27.297 に答える