2011-01-07 9 views

Respuesta

12

Un sin nombre union dentro de un struct tiene sentido, ya que le permite referirse a los miembros de la unión sin especificar su nombre, código, por tanto, más corto:

struct { 
    int a; 

    union { 
    int b, c, d; 
    }; 
} foo; 

Así que acceden a los miembros de la union es igual accediendo a un miembro de la estructura contenedora: foo.a y foo.b. De lo contrario, debe usar foo.union_name.b para acceder a un miembro de la unión.

Por supuesto, un programador de "usuario" que utilice dicha estructura debe saber que la configuración foo.c afecta el valor de foo.b y foo.d.

Por la misma razón la inversa se puede hacer, es decir, poner un anónimo struct dentro de un union:

union { 
    struct { 
    int a, b; 
    }; 

    int c; 
} foo; 

De esta manera foo.a y foo.b pueden usarse simultáneamente y foo.c se puede utilizar en otro caso.

No puedo pensar en ningún otro uso para estructuras o uniones anónimas. "Declarar" una estructura/unión anónima es un oxímoron y es como decir int; en lugar de int a;.

+0

Eso es realmente bueno, no lo sabía.¡Me has ahorrado muchas pulsaciones de teclas! – GWW

+1

Se trata de uniones anónimas, ¿qué hay de las estructuras sin nombre como en el ejemplo proporcionado por OP? –

0

En este caso, mapea la estructura (que contiene 4 bytes) y la int sin firmar (también 4 bytes) en la misma ubicación de memoria.

+0

Creo que no entendió el punto: el OP sabe para qué sirven los sindicatos, solo pregunta sobre las estructuras anónimas dentro de los sindicatos. – ereOn

+0

Pasando por el título "¿Para qué puedes usar una estructura o unión sin nombre?" No creo haberme perdido el punto. Pero sí, la última parte de la pregunta alude a struct cuando la vuelvo a leer. –

1

Puede usar una estructura anónima en una estructura o clase para agrupar algún valor que sean datos antiguos simples para facilitar la inicialización de la instancia (con un memset) pero no puede hacerlo porque la clase se deriva de otra.

Ejemplo:

#include <string.h> 
class Base 
{ 
private: 
    int field1; 
    int field2; 

public: 
    Base() 
    { 
     // initialize field1, field2 
    } 

    virtual void DoSomething(); 
}; 

class Derived : public Base 
{ 
private: 
    struct 
    { 
     int field2; 
     int field3; 
     int field4; 
     // ... 
     int field99; 
    } data; 

public: 
    Derived() 
    : Base() 
    { 
     memset(&data, 0, sizeof(data)); 

     // if you didn't group those value in an anonymous struct 
     // you would have to do something like that (not safe): 
     // memset(sizeof(Base) + (char*)this, 0, sizeof(Derived) - sizeof(Base)); 
    } 
}; 

Tenga en cuenta que existe alternativas mejores (en mi ejemplo usando un std :: vector o int [99]). Pero a veces puede ser útil.

+0

+1. es un buen ejemplo cuando la respuesta correcta no tenía ningún voto y la publicación que no respondió la pregunta tenía 6 votos –

5

Esto se debe principalmente a que struct y union son muy similares. En general, solo es útil tener estructuras anónimas dentro de los sindicatos, y las uniones anónimas dentro de las estructuras, pero las estructuras de anidación dentro de las estructuras o sindicatos dentro de los sindicatos son en su mayoría equivalentes a enumerar a sus miembros directamente.

Tenga en cuenta que las uniones no se deben utilizar para convertir valores, ya que no hay absolutamente ninguna garantía de disposición.

+0

+1 si solo fuera por la advertencia! El diseño de los datos es completamente a discreción del compilador, por lo que no solo no es portátil, sino que también puede cambiar según las opciones del compilador, etc. ... –

+0

¿El '#pragma pack' no tiene esas garantías y portabilidad? –

+1

#pragma no es portátil por definición. –

Cuestiones relacionadas