当前位置:  开发笔记 > 编程语言 > 正文

结构中C#fixed bool数组的大小和对齐是什么?

如何解决《结构中C#fixedbool数组的大小和对齐是什么?》经验,为你挑选了1个好方法。

在进行P/Invoke时,重要的是使数据布局匹配.

我们可以使用一些属性来控制struct的布局.

例如:

struct MyStruct 
{
    public bool f;
}

给出大小为4.虽然我们可以告诉编译器使它成为1字节bool以匹配C++类型bool:

struct MyStruct
{
    [MarshalAs(UnmanagedType.I1)]
    public bool f;
}

给出1的大小.

这些都有道理.但是当我测试固定的bool阵列时,我很困惑.

unsafe struct MyStruct
{
    public fixed bool fs[1];
}

给出4个字节的大小.和

unsafe struct MyStruct
{
    public fixed bool fs[4];
}

仍然给出4个字节的大小.但

unsafe struct MyStruct
{
    public fixed bool fs[5];
}

给出8的大小.

它看起来像在固定的bool数组中,bool元素的大小仍然是1个字节,但是对齐是4个字节.这与C++ bool数组不匹配,后者是1字节大小和对齐方式.

有人能解释一下吗?

更新:我终于找到了,原因是,bool类型在一个结构中,那么该结构永远不会是blittable!因此,不要指望内部具有bool类型的结构与C中的布局相同.

问候,翔.



1> Hans Passant..:

一个布尔值比较特殊,它可以追溯到丹尼斯里奇决定给不给C语言的布尔类型.这引起了大量的混乱,语言和操作系统设计者自己添加了它并做出了不兼容的选择.

它被添加到Winapi作为BOOL typedef.如果您不强制使用其他类型,则这是默认的封送处理.Typedef-ed为int以使其与C兼容,如您所知,需要4个字节.正如你所发现的那样,对齐到4,就像任何int一样.

它被添加到C++中.没有大小规范,大多数C++编译器实现选择单个字节进行存储.最值得注意的是Microsoft C++编译器,你最可能实现的实现.

它作为VARIANT_BOOL添加到COM Automation中.最初的目标是作为Visual Basic的新扩展模型来摆脱VBX限制,它变得非常流行,而且几乎所有Windows上的语言运行时都支持它.那时VB很大程度上受到16位操作系统敏感性的影响,VARIANT_BOOL需要2个字节.

所有三个本机运行时环境都可能是C#程序中互操作的目标.显然,CLR设计人员有一个非常困难的选择,必须选择1,2和4个字节.没有办法获胜,而CLR确实有机会猜测COM互操作,它无法知道你是否尝试与基于C的api或C++程序互操作.所以他们做出了唯一合乎逻辑的选择:没有一个.

包含bool的结构或类类型永远不会是blittable.即使应用[MarshalAs(UnmanagedType.U1)],也不会使它与CLR类型兼容.不太确定这是一个很好的决定,但它是他们制作的那个,所以我们必须处理它.

获得一个blittable结构是非常需要的,它避免了复制.它允许本机代码直接访问托管堆和堆栈.非常危险且许多破坏的pinvoke声明已经损坏了GC堆,而没有不安全关键字警报的通常好处.但不可能为速度而战.

使用就得到了一个blittable结构bool.请byte改用.您仍然可以通过使用属性包装struct成员来获取bool.不要使用自动实现的属性,您必须关心字节的位置.从而:

struct MyStruct 
{
    private byte _f;
    public bool f {
        get { return _f != 0; }
        set { _f = value ? 1 : 0; }
    }
}

本机代码不知道该属性.不要担心getter和setter的运行时开销,抖动优化器使它们消失,并且它们每个变为单个CPU指令.

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有