C# sizeof运算符在C中提供结构的额外大小#

C# sizeof运算符在C中提供结构的额外大小#,c#,struct,sizeof,C#,Struct,Sizeof,我试图使用sizeof运算符检查所有变量(值类型)的大小。我看过一本书,上面写着 对于所有其他类型,包括结构,sizeof运算符只能在不安全的代码块中使用 而且结构不应该包含任何引用类型的字段或属性 为此,我在项目属性中启用了不安全编译,并创建了如下结构- struct EmployeeStruct { int empId; long salary; } unsafe { size = sizeof(EmployeeStruct); } Console.W

我试图使用sizeof运算符检查所有变量(值类型)的大小。我看过一本书,上面写着

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

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

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

struct EmployeeStruct
{
    int empId;
    long salary;       
}
unsafe
{
   size = sizeof(EmployeeStruct);
}

Console.WriteLine("Size of type in bytes is: {0}", size);
并使用它如下-

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字节的大小吗?

你不需要使用不安全的代码。建议使用System.Runtime.InteropServices.Marshal.SizeOf()

例如:Marshal.SizeOf(newemployeestruct())

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

因此,对于:

struct EmployeeStruct
{
    int empId; // 4 bytes
    long salary;  8 bytes
}
//返回16而不是12(因为最小单位为8)

用于:

//返回16也

以及

   struct EmployeeStruct
   {
      int empId; // 4 bytes
      int empAge; // 4 bytes
      int IdCompany; // 4 bytes
      long salary;  8 bytes
   }
返回24而不是20(因为de最小单位为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,但是请记住,内存的实际大小是32,编译器使用32字节分配内存


注意。

您提供的链接告诉您:“而sizeof返回公共语言运行库分配的大小,包括任何填充”@EugenePodskal它改变了很多-在C#上寻找问题答案的人不会看关于C的问题,他们是非常不同的语言,即使答案是相同的。@GediminasMasaitis然后他们会找到这个问题并阅读副本(好吧,至少他们应该这样做).但是如果你认为这是值得的,那么你可以写一个适当的规范的C#特定的答案。在这种情况下,我还建议你将问题重命名为更易于搜索的,并且达到“sizeof返回的值大于预期”的程度或者类似的东西。注释DavidG的Thnx。你能告诉我为什么这个填充在获取任何内置类型(如int、float等)的大小时不会干扰。但是它为结构提供了额外的大小。很好的建议Eugene Podskal。我已经更新了标题以获得特定的注释。但是为什么一个带有thre的结构e
int
的大小是12而不是16?Thnx Gonzalo。但是System.Runtime.InteropServices.Marshall.SizeOf在Marshall之后返回非托管分配的大小,这不是真的吗?我们没有办法得到正确的托管或CLR分配的大小吗?我编辑了我的答案,也许我可以帮助你。注意。@Prakashtripath:正确。封送大小是--毫不奇怪--封送数据所需的缓冲区大小。sizeof size是结构消耗的内存量。没有理由认为这两个东西必须相同,而且它们通常不相同。Thnx Eric Lippert。您可以通过采样来计算大小。然而,这再次打开了一个小问题,为什么在sa中mple,Marshal.SizeOf不考虑填充?