Can we define a memory structure ( or File structure ) in C# #65051
-
I'm not a C/C++ developer,
|
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 15 replies
-
None of these are unique to C#, and all behave identically or similarly in C/C++ (some of them, particularly "type used" may depend on compiler flags, which is its own pain). Why are you asking, and what are you wanting to achieve? If you're trying to create a struct that exactly maps to some binary format, you'd normally look at the |
Beta Was this translation helpful? Give feedback.
-
@Clockwork-Muse May I ask about the > [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential,Pack = 1, Size = 7)]public struct Good { public int A; public bool B; public short C; }
> System.Runtime.CompilerServices.Unsafe.SizeOf<Good>()
7
> System.Runtime.InteropServices.Marshal.SizeOf<Good>()
10
> [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, Size = 7)]public struct Good { [FieldOffset(0)]public int A;[FieldOffset(0)] public bool B;[FieldOffset(0)] public short C; }
> System.Runtime.InteropServices.Marshal.SizeOf<Good>()
7
> System.Runtime.CompilerServices.Unsafe.SizeOf<Good>()
7
> [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential,Pack = 1, Size = 7)]public struct Good { public int A; public bool B; public short C; }
> System.Runtime.CompilerServices.Unsafe.SizeOf<Good>()
7
> System.Runtime.InteropServices.Marshal.SizeOf<Good>()
10 > public enum G : byte { Y,G,X }
> [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]public struct Good { public int A; public bool B; public short C; public G D; }
> System.Runtime.CompilerServices.Unsafe.SizeOf<Good>()
12
> System.Runtime.InteropServices.Marshal.SizeOf<Good>()
12
> [System.Runtime.InteropServices.StructLayout(LayoutKind.Auto)]public struct Good { public int A; public bool B; public short C; public G D; }
> System.Runtime.InteropServices.Marshal.SizeOf<Good>()
System.ArgumentException: Type 'Submission#59+Good' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
+ System.Runtime.InteropServices.Marshal.SizeOfHelper(System.Type, bool)
+ System.Runtime.InteropServices.Marshal.SizeOf<T>()
> System.Runtime.CompilerServices.Unsafe.SizeOf<Good>()
8
> |
Beta Was this translation helpful? Give feedback.
-
From the look of this and this
|
Beta Was this translation helpful? Give feedback.
-
Sort of. |
Beta Was this translation helpful? Give feedback.
-
If you want to deal with binary file formats that specify a certain endianess for their fields, and are concerned with not knowing the endianess of the executing system (which, as @Clockwork-Muse pointed out, is Little-Endian for the most popular platforms), one option is to leverage the type system: For representing a 64-bit unsigned little-endian integer, you could define your own type [StructLayout(LayoutKind.Sequential)]
readonly struct UInt64LE
{
private readonly ulong val;
private UInt64LE(ulong val) => this.val = val;
public static implicit operator ulong(UInt64LE num)
=> BitConverter.IsLittleEndian
? num.val
: BinaryPrimitives.ReverseEndianness(num.val);
public static implicit operator UInt64LE(ulong num)
=> BitConverter.IsLittleEndian
? new(num)
: new(BinaryPrimitives.ReverseEndianness(num));
} which handles the endianess-conversion transparently and can be employed in a file-structure mapping struct: [StructLayout(LayoutKind.Sequential)]
struct FileBinaryLayoutStruct
{
// ...
public UInt64LE field1;
// ...
} Notice how in the SharpLab sample the condition gets eliminated by the JIT-compiler, making the access as efficient as it could be in C/C++. Also, by utilizing the conversion operator, the accessing code looks the same as if it was a regular integer. I would therefore argue that C#'s typesystem suits very well for this kind of stuff, not even needing to specify the endianess at compile time via preprocessor macros. |
Beta Was this translation helpful? Give feedback.
None of these are unique to C#, and all behave identically or similarly in C/C++ (some of them, particularly "type used" may depend on compiler flags, which is its own pain).
Why are you asking, and what are you wanting to achieve? If you're trying to create a struct that exactly maps to some binary format, you'd normally look at the
StructLayout
Attribute, but there may be other or better ways to do whatever it is you're trying to achieve.