English 中文(简体)
工会与结构C
原标题:
  • 时间:2009-04-07 05:39:50
  •  标签:

这个问题背后的想法是理解的更深层次的概念使用联盟和以不同的方式使用它,以节省内存. .我的问题是—

让年代说有一个结构

struct strt
{
   float f;
   char c;
   int a;
}

和工会代表相同的结构

union unin
{
   float f;
   char c;
   int a;
}

If I allocate values to structure members one after another and then print them, it gets printed. But in case of union it doesn t happen, some overwriting is being done..

所以我需要找到一个方法,可以存储的值f c,一个使用联盟然后我可以打印是一样的。(适用于任何操作. .),但我在寻找这种技术. .谁能指引我或给我任何想法?

问题回答

如果你想看看一个结构体存储值,这将是这样的:

|0---1---2---3---|4---|5---6---7---8---|
|ffffffffffffffff|    |                | <- f: Where your float is stored
|                |cccc|                | <- c: Where your char is stored
|                |    |aaaaaaaaaaaaaaaa| <- a: Where your int is stored

所以当你改变f的值,你实际上是改变字节0 - 3。当你改变你的字符,你实际上是改变字节4。当你改变你的智力,你实际上是改变字节5 - 8。

如果你现在看看工会如何存储值,这将是这样的:

|0---1---2---3---|
|ffffffffffffffff| <- f: where your float is stored
|cccc------------| <- c: where your char is stored
|aaaaaaaaaaaaaaaa| <- a: where your int is stored

现在,当我改变f的值,我改变字节0 - 3。从c存储在字节0,当你改变,你也改变c和一个!当你改变c、f和a -你改变的一部分,当你改变,你改变s c f。“覆盖”的地方正在发生的事情。当你包3值到一个内存地址,你不是“节省空间”;你只是创建3个不同的观察方式和改变相同的数据。你不真的有一个int,浮动,和一个char联盟——在物理层面,你已经有32位,这可能被视为一个int,浮动或char。改变一个是< em > < / em >改变别人。如果你不希望他们改变对方,然后使用一个结构体。

这就是为什么gcc的告诉你,你的struct 9字节长,虽然你的工会是只有4——它不是节省空间,这年代,结构和工会不是一回事。

我认为你误解了一个<代码>联盟的目的> < /代码。

<代码>联盟> < /代码,顾名思义,定义一个结构,<强>所有成员占据相同的内存空间< / >强。而<代码>结构> < /代码的地方它的每个成员在不同的记忆在一个连续的区域。

与你的联盟,当你写:

union foo;
foo.c = 3;

然后<代码> foo。< /代码>和<代码> foo。f > < /代码都将被改变。这是因为<代码>。< /代码>,<代码>。c < /代码>,<代码>。f > < /代码存储在同一内存位置< em > < / em >。因此,每个成员的联盟是一个不同的“视图”相同的内存。这不会发生在<代码> struct > < /代码,因为所有的成员都是独特的,彼此分开。

没有办法在这个行为< em >,因为它年代故意的。< / em >

我认为你是误会工会。

使用工会背后的想法是脚趾节省内存……

是的,那年代的一个原因

…和获得的结果相当于结构……

没有

it s 没有t equivalent. They looks similar in source code, but it is a completely different thing. Like apples and airplanes.

Unions are a very, very low level construct that allows you to see a piece of memory as if storing any of its "members", but you only can use one at a time. Even the use of the word "member" is extremely misleading. They should be called "views" or something, 没有t members.

当你写:

union ABCunion
{
    int a;
    double b;
    char c;
} myAbc;

You are saying: "take a piece of memory big e没有ugh for the biggest among an int, a char and a double, and lets call it myAbc.

In that memory, 没有w you can store either an int, or a double, or a char. If you store an int, and then store a double, the int is gone forever.

点什么呢?

有两个主要用途工会。

一)歧视存储

这上面所做的。我拿一块内存,赋予它不同的含义取决于上下文。有时是显式的上下文中(你保留一些变量,表示“类”的变量存储),有时它可以隐式(基础部分的代码,您可以告诉哪一个必须使用)。无论哪种方式,代码需要能够算出来,或者你不能够做任何合理的变量。

一个典型的例子(显式)是:

struct MyVariantType
{
    int typeIndicator ;  // type=1 -> It s an int, 
                         // type=2 -> It s a  double, 
                         // type=3 -> It s a  char
    ABCunion body;
};

For example, VB6 s "Variants" are Unions 没有t unlike the above (but more complex).

b) Split representation This is sometimes useful when you need to be able to see a variable as either a "whole" or as a combination of parts. It s easier to explain with an example:

union DOUBLEBYTE
{
    struct
    {
        unsigned char a;
        unsigned char b;
    } bytes;
    short Integer;        
} myVar;

这年代短int“联合”两个字节。现在,您可以查看相同的值作为一个短整型(myVar.Integer),或者您可以简单地研究单个字节(myVar.bytes价值的一部分。一个和myVar.bytes.b)。

Note that this second use is 没有t portable (I m pretty sure); meaning that it s 没有t guaranteed to work across different machine architectures; but this use is absolutely essential for the kind of tasks for which C was designed (OS implementation).

工会包含一组<强>互斥< /强>数据。

在您的特定示例中,您可以存储浮动(f < em > < / em >), char (< em > c < / em >)或int (< em > < / em >)。然而,记忆只会分配给项目< / em > < em >大联盟。所有项目的联盟将共享相同的<强> < /强>,内存的一部分。换句话说,写一个值进入联盟之后,另一个将导致第一个值被覆盖。

你需要回去问问自己<强>你造型< /强>:

  • 你真正想要的值f < em > < / em >, < em > c < / em >和< em > < / em >是互斥(即只有一个值可以存在一次)?如果是这样,考虑使用一个联盟与一个枚举值(存储在联盟)表示,工会成员是“活跃”在任何一个特定的时间点。这将允许您获得的内存使用联盟的好处,代价是更危险的代码(任何维护需要注意,值是相互排斥的,即它的确是一个联盟)。< em >只考虑这个选项如果要创建许多这样的工会和内存保护是至关重要的(例如,在嵌入式cpu)。你甚至可能不会最终节省内存,因为您需要创建枚举变量在堆栈上它也会占用内存。< / em >

  • 你想要这些值同时活跃,不相互干扰?如果是这样的话,您将需要使用一个struct相反(当你把第一个例子)。这将使用更多的内存,当你实例化一个结构,分配给它的内存是所有成员的总和(加上一些填充到最近的词界)。< em >除非内存保护是至关重要的(见前一个例子),我支持这种方法。< / em >

<强>编辑:< /强>

(非常简单的)如何使用枚举的例子与工会:

typedef union
{
    float f;
    char c;
    int a;
} floatCharIntUnion;

typedef enum
{
    usingFloat,
    usingChar,
    usingInt
} unionSelection;

int main()
{
    floatCharIntUnion myUnion;
    unionSelection selection;

    myUnion.f = 3.1415;
    selection = usingFloat;
    processUnion(&myUnion, selection);

    myUnion.c =  a ;
    selection = usingChar;
    processUnion(&myUnion, selection);

    myUnion.a = 22;
    selection = usingInt;
    processUnion(&myUnion, selection);
}

void processUnion(floatCharIntUnion* myUnion, unionSelection selection)
{

    switch (selection)
    {
    case usingFloat:
        // Process myUnion->f
        break;
    case usingChar:
        // Process myUnion->c
        break;
    case usingInt:
        // Process myUnion->a
        break;
    }
}

这是一个经典的例子使用联合存储数据取决于外部标志。

int、浮动和char *所有占据同一个地方联盟,他们不是连续的,如果你需要存储,这年代结构你寻找,不是一个联盟。

结构的规模最大的联盟+类型的大小,因为它年代以外的联盟。

#define TYP_INT 0
#define TYP_FLT 1
#define TYP_STR 2

typedef struct {
    int type;
    union data {
        int a;
        float b;
        char *c;
    }
} tMyType;

static void printMyType (tMyType * x) {
    if (x.type == TYP_INT) {
        printf ("%d
", x.data.a;
        return;
    }
    if (x.type == TYP_FLT) {
        printf ("%f
", x.data.b;
        return;
    }
    if (x.type == TYP_STR) {
        printf ("%s
", x.data.c;
        return;
    }
}

printMyType函数将正确检测什么年代中存储结构(除非你撒谎)并打印相关的值。

填充其中之一时,你要做的:

x.type = TYP_INT;
x.data.a = 7;

x.type = TYP_STR;
x.data.c = "Hello";

和一个给定的<代码> x > < /代码只能一次一件事。

谁试:谁倒霉

x.type = TYP_STR;
x.data.a = 7;

They re asking f或 trouble.

工会时通常使用的只有一个低于将存储在一个实例在任何给定的时间点。即可以存储一个浮点数,一个字符或一个int在任何瞬间。这是节省内存,而不是分配额外的浮动和int /不同的内存,当你要使用它来存储字符。分配的内存数量=联盟最大的类型。

union unin
{
   float f;
   char c;
   int a;
}

联盟的其他用途是当你想要存储的东西部分,让坐在你可能想要模型包含上注册成为联盟字节,字节和复合价值低。所以你可以复合值存储到工会和使用成员获得通过其他成员。





相关问题
热门标签