0

我有一个结构:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct FieldIndex {
   public fixed byte Meta[16];
}

第一个字节是TypeCode. 剩下的 15 个字节是一个 UTF8 编码的字符串。

我正在使用以下内容来填充nameBuf字节数组:

  private static string GetMetaName (FieldIndex meta) {
     var idx = 0;
     var bytesOut = 1;
     var nameBuf = new byte[Indexer.MAXFIELDNAMELENGTH];   // 15

     while (bytesOut < Indexer.MAXFIELDLENGTH) {           // 16
        nameBuf[idx] = *(byte*)((byte*)&meta + bytesOut);

        ++bytesOut;
        ++idx;
     }

     //var src = (byte*)&field.meta + 1;
     //fixed (byte* b = nameBuf) {
     //   *((byte*)b) = (byte)src;
     //}

     return BinaryConverter.ToString(nameBuf, 0, Indexer.MAXFIELDNAMELENGTH, Indexer.DefaultEncoding);
  }

在上面的注释代码中,我试图在没有while迭代的情况下完成相同的任务,但它不起作用(没有编译错误,只是错误的插值)。我可以nameBuf在没有while-loop 的情况下分配吗?

更新
我也更喜欢使用(byte*)而不是Marshal.Copy.

4

2 回答 2

1

您可以尝试在上下文中使用Marshal.Copy静态方法:unsafe

unsafe
{
    Marshal.Copy(new IntPtr(meta), nameBuf, 1, nameBuf.Length);
}
于 2015-10-02T15:44:38.797 回答
1

当您可以通过这种方式轻松地做到这一点时,用这种不安全的方式来做这件事没有多大意义:

[StructLayout(LayoutKind.Sequential)]
struct FieldIndex {
   public byte Typecode;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
   private byte[] Utf8string;
   public string GetString() {
      return Encoding.UTF8.GetString(Utf8string, 0, 15);
   }
}

没有while循环,任务完成。该指针仍然存在并且同样有效,您只是不再看到它。如果您担心过于频繁地调用 GetString() 方法,那么只需声明另一个公共类并将其保留在内部。

于 2015-10-02T17:18:32.483 回答