这个 C# 结构体的大小是多少?

发布于 2024-09-25 09:52:57 字数 182 浏览 9 评论 0原文

存储在List中时是12字节还是16字节?

public struct DataPoint
{
    DateTime time_utc;
    float value;
}

C#中有sizeof函数吗?

Is it 12 bytes or 16 bytes when stored in a List<DataPoint>?

public struct DataPoint
{
    DateTime time_utc;
    float value;
}

Is there any sizeof function in C#?

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

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

发布评论

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

评论(6

小嗷兮 2024-10-02 09:52:57

Take a look at @Hans Passant's answer here for interesting background on this issue, esp. with regard to the limitations of Marshal.Sizeof.

温暖的光 2024-10-02 09:52:57

CLR 可以根据自己的需要自由地在内存中布置类型。所以不可能直接给出“the”尺寸。

但是,对于结构,可以使用 StructLayout 属性

  • Auto:运行时自动选择合适的布局。
  • 顺序:对象的成员按顺序布局,并根据 StructLayoutAttribute.Pack 值对齐。
  • 显式:显式控制每个成员的精确位置。

C# 编译器自动将顺序布局类型应用于任何结构。在 x86 或 x64 计算机上,Pack 值分别默认为 4 或 8。所以你的结构体的大小是 8+4=12(x86 和 x64)。


与类型在内存中的布局方式无关,也可以使用 Marshal 类。编组器在编组类型时应用多种转换,因此结果并不总是与 CLR 布置类型的方式相同。 (例如,bool 在内存中占用 1 个字节并进行对齐,而编组器将 bool 编组为 4 个字节。)

The CLR is free to lay out types in memory as it sees fit. So it's not possible to directly give "the" size.

However, for structures it's possible to restrict the freedom of the CLR using the StructLayout Attribute:

  • Auto: The runtime automatically chooses an appropriate layout.
  • Sequential: The members of the object are laid out sequentially and are aligned according to the StructLayoutAttribute.Pack value.
  • Explicit: The precise position of each member is explicitly controlled.

The C# compiler automatically applies the Sequential layout kind to any struct. The Pack value defaults to 4 or 8 on x86 or x64 machines respectively. So the size of your struct is 8+4=12 (both x86 and x64).


Unrelated from how a type is laid out in memory, it's also possible to marshal a type in .NET using the Marshal Class. The marshaller applies several transformations when marshalling a type, so the result is not always the same as the way the CLR laid out the type. (For example, a bool takes 1 byte in memory plus alignment, while the marshaller marshals a bool to 4 bytes.)

如日中天 2024-10-02 09:52:57

它将是 12 个字节(4 个字节用于 float,8 个字节用于 DateTime);
Marshal.SizeOf 将返回 16,因为默认打包是 8 字节对齐。
这是一篇关于结构和打包的好文章。它给出了实际发生的事情的完整描述。

It will be 12 bytes (4 for float, 8 for DateTime);
Marshal.SizeOf will return 16 because the default packing is 8 bytes aligned.
This is a good article on structs and packing. It gives a full description of whats actually happening.

迷爱 2024-10-02 09:52:57

尝试 Marshal.SizeOf(typeof(DataPoint))

Try Marshal.SizeOf(typeof(DataPoint))

铃予 2024-10-02 09:52:57

以下代码基于此 StackOverflow 问题和答案< /a>:

        /// <summary>
        /// Computes the size of the given managed type. Slow, but reliable. Does not give the same result as Marshal.SizeOf
        /// NOTE: this is not the same as what is the distance between these types in an array. That varies depending on alignment.
        /// </summary>
        public static int ComputeSizeOf(Type t)
        {
            // all this just to invoke one opcode with no arguments!
            var method = new DynamicMethod("ComputeSizeOfImpl", typeof(int), Type.EmptyTypes, typeof(Util), false);
            var gen = method.GetILGenerator();
            gen.Emit(OpCodes.Sizeof, t);
            gen.Emit(OpCodes.Ret);
            var func = (Func<int>)method.CreateDelegate(typeof(Func<int>));
            return func();
        }

我认为您可能想知道的问题不是类型的大小是多少,而是列表中两个连续元素之间的距离是多少。这是因为正如其他人提到的,对齐可以发挥作用。

我相信最好使用 Marshal.UnsafeAddrOfPinnedArrayElement(),但很难正确使用,特别是因为 List 没有公开公开支持阵列。

The following code is based on this StackOverflow question and answers:

        /// <summary>
        /// Computes the size of the given managed type. Slow, but reliable. Does not give the same result as Marshal.SizeOf
        /// NOTE: this is not the same as what is the distance between these types in an array. That varies depending on alignment.
        /// </summary>
        public static int ComputeSizeOf(Type t)
        {
            // all this just to invoke one opcode with no arguments!
            var method = new DynamicMethod("ComputeSizeOfImpl", typeof(int), Type.EmptyTypes, typeof(Util), false);
            var gen = method.GetILGenerator();
            gen.Emit(OpCodes.Sizeof, t);
            gen.Emit(OpCodes.Ret);
            var func = (Func<int>)method.CreateDelegate(typeof(Func<int>));
            return func();
        }

I think the question you are probably wondering, is not what is the size of the type but what is the distance between two contiguous elements in the List. This is because alignment can play a role, as mentioned by others.

I believe the solution to that problem would best be achieved using Marshal.UnsafeAddrOfPinnedArrayElement(), but is very difficult to use correctly, particularly because the List does not expose publicly the backing array.

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