Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C++;C中的联合# 我将C++中的一个库翻译成C,关键字“联合”一次。在结构中_C#_C++_Unions - Fatal编程技术网

C# C++;C中的联合# 我将C++中的一个库翻译成C,关键字“联合”一次。在结构中

C# C++;C中的联合# 我将C++中的一个库翻译成C,关键字“联合”一次。在结构中,c#,c++,unions,C#,C++,Unions,把它翻译成C的正确方法是什么?它有什么作用?它看起来像这样 struct Foo { float bar; union { int killroy; float fubar; } as; } 您可以使用显式字段布局: [StructLayout(LayoutKind.Explicit)] public struct SampleUnion { [FieldOffset(0)] public float bar; [Fi

把它翻译成C的正确方法是什么?它有什么作用?它看起来像这样

struct Foo {
    float bar;

    union {
        int killroy;
        float fubar;
    } as;
}

您可以使用显式字段布局:

[StructLayout(LayoutKind.Explicit)] 
public struct SampleUnion
{
    [FieldOffset(0)] public float bar;
    [FieldOffset(4)] public int killroy;
    [FieldOffset(4)] public float fubar;
}

未经测试。这是因为两个变量在结构中的位置相同。当然,您只能使用其中一个


有关C/C++中的联合的更多信息联合用于在同一内存位置中覆盖不同的成员,因此如果有int和float的联合,它们都使用相同的4字节内存来存储,显然写入一个会损坏另一个(因为int和float具有不同的位布局)

在.Net中,微软选择了更安全的选择,但没有包括此功能


编辑:除了interop,我个人会忽略联合,将Killroy和Fubar作为单独的字段实现

public struct Foo
{
    float bar;
    int Kilroy;
    float Fubar;
}

使用UNION可以节省由int分配的32位内存……这些天来不会创建或破坏应用程序。

如果不知道如何使用它,你就无法真正决定如何处理它。如果它只是用来节省空间,那么您可以忽略它,只使用一个结构

然而,这通常不是使用工会的原因。使用它们有两个常见的原因。一种是提供两种或多种方式来访问相同的数据。例如,int和4字节数组的并集是分离32位整数字节的多种方法之一

另一种情况是结构中的数据来自外部源,如网络数据包。通常,包含联合体的结构的一个元素是一个ID,它告诉您联合体的有效风格


在这两种情况下,您都不能盲目地忽略联合并将其转换为两个(或多个)字段不重合的结构。

如果您使用联合将一种类型的字节映射到另一种类型,那么在C中,您可以使用位转换器

float fubar = 125f; 
int killroy = BitConverter.ToInt32(BitConverter.GetBytes(fubar), 0);


注意,只有当涉及的类型是基元类型(如int和float)时,这才有效。一旦涉及到对象,它就不允许您使用。它是用于值类型(如枚举)还是仅用于基元类型?如果您有其他复杂类型,则第二个类型可以是与其他类型转换的属性。取决于Union的用法以及它在您正在移植的其他代码中的使用方式。“当然,您只能使用其中一种。”可能不清楚。您可以访问和设置它们,但它们会相互覆盖。我想澄清这一点。@Khoth您可以在结构的字段中保存任何内容。与显式结构布局相同。这可能是因为.NET是更高级的,您可能不必担心显式序列化数据以及在小端和大端机器之间传输数据。联合提供了一种很好的转换方法,使用前面注释中提到的技巧。显式布局结构的使用不限于互操作。非引用类型的原语和公共成员可以用完全定义的行为以任意方式覆盖非引用类型的其他原语和公共成员,无论代码是否将相关结构传递给外部代码。在这方面,.NET支持比“modern”C更低级别的构造。这可能不起作用,这取决于库的其他部分如何访问它,在某些情况下,您可以写入一个实例并从另一个实例读取,以获得相同的数据,但格式略有不同,如果你把它分成两个不同的部分,这个功能就会被破坏variables@KPexEA我同意。但是,如果另一方面,它是一种联合类型,其中一些标志指示两个字段中的哪一个是合适的,那么这将很好地工作。我认为真正重要的是在决定如何移植它之前,了解每种情况下联合的用法和目的。如果您想创建一个包含10或20个联合类型的结构,因为结构是byval,每个参数传递几个字节要比传递1k快得多。这可能更安全,但当您与提供此类数据结构的C库交互时,C#中的这一决定甚至破坏了C/C++结构的基本封装。我正在尝试处理这样的事情:struct LibrarySType{AnotherType*anotherTypeBuff;int-oneSetOfFlags;int-oneothersetofflags;union{struct{int-structMember1;..}oneUseOfThisLibraryType;struct{char*structMember2;..}anotherUseOfThisLibraryType;..}u;int64*moreStuff;…你明白了吗}现在,我并没有发明这种聪明的数据结构,但它是我需要的供应商API的一部分。我认为Steve的回答中很重要的一点是,你真的需要了解你正在移植的特定联盟的用法。在C#中可能还有其他的结构可以以更优雅的方式满足需要。虽然我理解@AaronLS的意思,但是如果能链接到文档或一些关于在C#中优雅地实现这一点的常用方法,那将是很好的。我可以根据用法猜测一些非常基本的方法,比如使用属性返回联合的一个值的“强制转换”,就像它是另一个成员一样。但是想知道对于常见的场景还有什么其他优雅的方式。
int killroy = 125;
float fubar = BitConverter.ToSingle(BitConverter.GetBytes(killroy), 0);
public class Foo
{
    public float bar;
    public int killroy;

    public float fubar
    {
        get{ return (float)killroy;}
        set{ killroy = (int)value;}
    }
}