像在 C 中一样在 C# 中使用 struct - 可以吗?

发布于 2024-12-03 10:09:08 字数 418 浏览 5 评论 0原文

我正在读取特定格式的二进制文件,并且习惯于能够将数据块转换为结构,然后读取该结构以从二进制数据文件中提取字段。

我正在尝试这样做,但在 C# 中失败了,它们看起来更像是类,而不是 C 意义上的结构。可以做我想做的事吗?例如..

public struct Datum {
    byte type;
    ushort payload;
}

public struct DiskPage {
    ushort pageNumber;
    Datum[] data = Datum[170];
}

我希望能够读取文件的 512 字节并将其转换为 DiskPage,然后能够从 DiskPage 结构中读取值。这在 C# 中可能吗?或者还有其他首选方法吗?我应该将该代码保留在 C 中并将其链接吗?

谢谢! 礼萨

I am reading a binary file of a specific format, and am used to being able to cast a block of data to a struct then reading the struct to pull fields out of the binary datafile.

I'm trying to do this but failing in C#, they seem more like classes than structures in the C sense. Is it possible to do what I want? For example..

public struct Datum {
    byte type;
    ushort payload;
}

public struct DiskPage {
    ushort pageNumber;
    Datum[] data = Datum[170];
}

I want to be able to read 512 bytes of a file and cast it to a DiskPage, then to be able to read the values from the DiskPage structure. Is this possible in c# - or is there another preferred approach? Should I just leave that code in C and link it in?

Thanks!
Reza

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鹤仙姿 2024-12-10 10:09:08

默认情况下,编译器不尊重字段的顺序(它也可能会移动字段并在内存中留下间隙= 打包)。通过使用 StructLayout 您可以强制执行不同的行为(默认、顺序或显式)。

使用 MarshalAs 作为字段上的特定选项。小心字节顺序。

[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public struct MySystemTime 
{
   [FieldOffset(0)]public ushort wYear; 
   [FieldOffset(2)]public ushort wMonth;
   [FieldOffset(4)]public ushort wDayOfWeek; 
   [FieldOffset(6)]public ushort wDay; 
   [FieldOffset(8)]public ushort wHour; 
   [FieldOffset(10)]public ushort wMinute; 
   [FieldOffset(12)]public ushort wSecond; 
   [FieldOffset(14)]public ushort wMilliseconds; 
}

The compiler doesn't respect ordering of your fields by default (also it might move the fields and leave gaps in the memory = Packing). By using StructLayout you can enforce a different behavior (Default, Sequential, or Explicit).

Use MarshalAs for specific options on a field. Be careful with endianess.

[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public struct MySystemTime 
{
   [FieldOffset(0)]public ushort wYear; 
   [FieldOffset(2)]public ushort wMonth;
   [FieldOffset(4)]public ushort wDayOfWeek; 
   [FieldOffset(6)]public ushort wDay; 
   [FieldOffset(8)]public ushort wHour; 
   [FieldOffset(10)]public ushort wMinute; 
   [FieldOffset(12)]public ushort wSecond; 
   [FieldOffset(14)]public ushort wMilliseconds; 
}
追我者格杀勿论 2024-12-10 10:09:08

我建议您阅读掌握 C# 结构,其中讨论了如何使用封送处理 (特别是 Marshal.Copy)用于此目的。

I suggest you read Mastering C# structs that discusses using marshaling (Marshal.Copy in particular) for that purpose.

≈。彩虹 2024-12-10 10:09:08

如果在启用 Unsafe 选项的情况下进行编译,则可以在 C# 中使用固定数组。
您还可以使用指针。

internal unsafe struct MyStruct
{
    public fixed byte MyFixedArray[128];
    public byte* MyPointer;
}

最好使用编组、字段偏移并避免不安全代码。
如果您确实需要一小部分代码,请使用不安全的代码。
如果可以避免的话,不要向外部世界公开固定数组或指针(接口或公共类\结构)。

You can use fixed arrays in C# if you compile with Unsafe option enabled.
You can also use pointers.

internal unsafe struct MyStruct
{
    public fixed byte MyFixedArray[128];
    public byte* MyPointer;
}

It is preferred to use marshalling, field offset and avoid unsafe code.
Use unsafe code if you really need too in small portion of your code.
Don't expose to external world a fixed array or a pointer (interfaces or public classes\structs) if you can avoid it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文