-4

using the following struct:

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

...how would I go about computing the checksum value if it "is computed by breaking the structure into 37 unsigned shorts, adding them together, and taking the least significant 16 bits of the result"?

Gerard
  • 73
  • 6
  • 7
    You seem to have gotten the wrong idea about how Stack Overflow works. You show us your code, explain what you tried and where you are stuck, and we try to help. You didn't show the code for the problem. – Oded Dec 14 '12 at 19:55
  • Or, to say that @Oded expressed in another way: Maybe you have no code, but you tell us how far you've got and what exactly is your question. For example, do you have any problem at adding unsigned shorts? Because that's a part of what you seem to be asking for. – O. R. Mapper Dec 14 '12 at 19:57
  • Thanks for putting me in my place Oded. Have yourself a great day! – Gerard Dec 14 '12 at 20:06
  • 2
    This community works a certain way. I am explaining how it works. Take it or leave it. – Oded Dec 14 '12 at 20:58

2 Answers2

2

I would start by creating a byte array from the struct (see here), then using BitConvert.ToUInt16() to read the ushort values and adding from there.

Community
  • 1
  • 1
Jon B
  • 51,025
  • 31
  • 133
  • 161
1

Here's one way to do it, but whether that will meet the requirements...who knows. Does cpu endianness matter?

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

}

or you could drop down to unsafe code and do something like:

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

But if there's any padding in the structure or at the end of the structure, I don't believe you're guaranteed that padding octets are zeroed, so your results might be impacted. And if your structure contains an odd number of octets, you're likely to throw an exception trying to read past the end of the struct...or compute an incorrect value.

And of course, you could serialize the struct to a memory stream and then read that as a stream of ushorts:

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

But again, that's making assumptions about layout and endianness and padding. And you'll almost certainly throw and exception if the structure size is odd.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135