sizeof 运算符在 C# 中给出结构的额外大小 [重复]

Posted

技术标签:

【中文标题】sizeof 运算符在 C# 中给出结构的额外大小 [重复]【英文标题】:sizeof operator gives extra size of a struct in C# [duplicate] 【发布时间】:2016-06-27 21:13:14 【问题描述】:

我正在尝试使用 sizeof 运算符检查所有变量(值类型)的大小。我浏览了其中一个msdn article,其中写着

对于所有其他类型,包括结构,sizeof 运算符只能用于不安全的代码块中

结构体不应包含任何引用类型的字段或属性

为此,我在我的项目属性中启用了不安全编译并创建了如下结构-

struct EmployeeStruct

    int empId;
    long salary;       

并按如下方式使用它-

unsafe

   size = sizeof(EmployeeStruct);


Console.WriteLine("Size of type in bytes is: 0", size);

在这里,我得到的输出是字节类型的大小为:16,但是通过查看结构,它应该是 12(4 表示 int,8 表示 long)。 有人可以在这里帮助我理解为什么我会得到 4 字节的额外大小吗?

【问题讨论】:

您提供的链接告诉您:“而 sizeof 返回由公共语言运行时分配的大小,包括任何填充 @EugenePodskal 它发生了很大变化——在 C# 上寻找问题答案的人不会看关于 C 的问题,它们是非常不同的语言,即使答案是相同的。 @GediminasMasaitis 然后他们会找到这个问题并阅读副本(嗯,至少他们应该)。但是,如果您认为值得付出努力,那么您可以编写一个适当的规范 C# 特定答案。在这种情况下,我还建议您将问题重命名为更易于搜索和直截了当的“sizeof 返回值大于预期”或类似的内容。 感谢 DavidG 的评论。你能告诉我更多为什么这个填充在获取任何内置类型(如 int、float 等)的大小时不会产生干扰,但是它为结构提供了额外的大小。 好建议 Eugene Podskal。我已更新标题以获得具体评论。 【参考方案1】:

您不需要使用不安全的代码。推荐使用 System.Runtime.InteropServices.Marshal.SizeOf()

例如:Marshal.SizeOf(new EmployeeStruct());

返回 16 而不是 12,因为内存中的默认包大小是 8。

所以,对于:

struct EmployeeStruct

    int empId; // 4 bytes
    long salary;  8 bytes

//返回 16 而不是 12(因为最小单位是 8)

为:

 struct EmployeeStruct
 
    int empId; // 4 bytes
    int empAge; // 4 bytes
    long salary;  8 bytes
  

//也返回16

为了

   struct EmployeeStruct
   
      int empId; // 4 bytes
      int empAge; // 4 bytes
      int IdCompany; // 4 bytes
      long salary;  8 bytes
   

返回 24 而不是 20(因为最小单位是 8)

我不知道你想要什么,但是如果你需要每个字段大小的总和,你可以试试这个函数:

    public int SizeOf(Type t)
    
        int s = 0;
        var fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
        foreach (var f in fields)
        
            var x = f.FieldType;
            s += x.IsPrimitive ? Marshal.SizeOf(x) : SizeOf(x);
        

        return s;
    

对于您的情况,它返回 12 而不是 16,您可以将它用于复杂的结构,例如:

    struct EmployeeStruct
    
        int field1; // 4 bytes
        long field2; // 8 bytes
        Person p; // 12 bytes
    

    struct Person
    
        int field1; // 4 bytes
        long field2; // 8 bytes
      

SizeOf(typeof(EmployeeStruct) 将返回 24 而不是 32,但请记住,REAL SIZE ON MEMORY 是 32,编译器使用 32 字节分配内存。

问候。

【讨论】:

但是为什么一个包含三个int的结构的大小是12而不是16? Thnx Gonzalo。但是 System.Runtime.InteropServices.Marshal.SizeOf 在编组后返回非托管分配的大小不是真的吗?难道我们没有办法获得正确的托管或 CLR 分配的大小吗? 我编辑了我的答案,也许我可以帮助你。问候。 @PrakashTripathi:正确。封送大小是 - 毫不奇怪 - 封送数据所需的缓冲区大小。 sizeof size 是结构消耗的内存量。这两件事没有理由必须相同,而且通常情况并非如此。 感谢 Eric Lippert。你采样来计算尺寸就像魅力一样。但是,这再次引发了一个小问题,即为什么在您的示例中 Marshal.SizeOf 不考虑填充?

以上是关于sizeof 运算符在 C# 中给出结构的额外大小 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

sizeof(类)

结构 C# 的大小

类型的 sizeof() 运算符

sizeof如何计算结构的大小

Marshal.SizeOf 给出错误的大小

Sizeof 运算符返回不正确的大小? [复制]