Si no hay por qué? ¿Usos de la unión sobre la estructura?¿Podemos usar el puntero en unión?
Respuesta
Puede usar cualquier tipo de datos en una unión, no hay ninguna restricción.
En cuanto al uso de uniones sobre estructuras, las estructuras presentan sus datos secuencialmente en la memoria. Esto significa que todos sus subcomponentes están separados.
Los sindicatos, por otro lado, utilizan la misma memoria para todos sus subcomponentes, por lo que solo puede existir uno a la vez.
Por ejemplo: se utilizan
+-----+-----+
struct { int a; float b } gives | a | b |
+-----+-----+
^ ^
| |
memory location: 150 154
|
V
+-----+
union { int a; float b } gives | a |
| b |
+-----+
estructuras en las que un "objeto" se compone de otros objetos, como un objeto de punto consta de dos números enteros, los que están siendo la x e y las coordenadas:
typedef struct {
int x; // x and y are separate
int y;
} tPoint;
Las uniones se usan generalmente en situaciones en las que un objeto puede ser una de muchas cosas, pero solo una a la vez, como un sistema de almacenamiento sin tipo:
typedef enum { STR, INT } tType;
typedef struct {
tType typ; // typ is separate.
union {
int ival; // ival and sval occupy same memory.
char *sval;
}
} tVal;
Son útiles para guardar memoria, aunque eso tiende a ser cada vez menos importante en la actualidad (aparte del trabajo de bajo nivel, como los sistemas integrados) por lo que no se ve mucho.
Bueno, de acuerdo con la norma ISO/IEC 9899: TC3 (el estándar C99):
Un tipo de unión se describe un conjunto no vacío superposición de objetos miembro, cada uno de que tiene un nombre opcionalmente especificado y posiblemente distinta tipo.
En resumen, el espacio de memoria de los miembros de la unión se superpone, y los nombres que le da a los miembros de la unión le permiten leer la memoria en esa ubicación de tamaño. Considere:
#include <stdio.h>
#include <stdint.h>
typedef union
{
struct
{
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
};
uint32_t x;
} somenewtype;
typedef union
{
uint32_t* p;
uint8_t* q;
} somepointer;
int main(int argc, char** argv)
{
uint32_t r;
uint8_t s;
somenewtype z;
somepointer p;
r = 0x11223344; s = 0x11;
z.x = 0x11223344;
p.p = &r;
p.q = &s;
printf("%x%x%x%x\n", z.d, z.c, z.b, z.a);
printf("%x %x\n", *(p.p), *(p.q));
}
En el primer printf, lo que estamos haciendo es imprimir las piezas de 8 bits del entero de 32 bits. Esperando, por supuesto, que no haya relleno en esa estructura anónima.
En la segunda impresión? Tenía que pasar por el uso de GDB de entender, pero lo hice:
p.p = (uint32_t *) 0x7fffffffde5c;
p.q = (uint8_t *) 0x7fffffffde5b "\021D3\"\021P\337\377\377\377\177";
p.p = (uint32_t *) 0x7fffffffde5b;
Bueno, por supuesto, los punteros son todos del mismo tamaño, por lo que la asignación de p.q
sobrescribe la dirección de p.p
. Sospecho que la desreferenciación de la dirección del entero de 32 bits a un puntero de 8 bits es la impresión de "lo que sea en esa ubicación + 32 bits de tamaño" que, casualmente, para mí es 22334411
. Pero sospecho que, en ese momento, el comportamiento no está definido.
De todos modos, el punto de que era pequeño ejercicio para demostrar que:
- uniones se pueden utilizar para acceder a la misma posición de memoria a través de un modificador de "tipo" diferente.
- Tiene que tener cuidado con lo que hace y comprender el tipo subyacente que está utilizando. Si va a usar punteros, tenga cuidado con sus modificaciones ya que podría comenzar a señalar quién sabe qué.
Debo señalar que puedo ver el uso práctico para somenewtype
pero no para somepointer
- que fue un ejemplo artificioso que estaba bastante seguro de que se rompa.
- 1. ¿Podemos usar & en url?
- 2. ¿Podemos usar el enhebrado en PL/SQL?
- 3. ¿Podemos utilizar este puntero dentro del constructor
- 4. ¿Por qué no podemos usar el doble puntero para representar dos matrices dimensionales?
- 5. ¿Podemos usar pom.xml en ANT
- 6. ¿Podemos usar union en hibernate?
- 7. ¿Cuándo podemos usar el método ClearAllPools?
- 8. ¿podemos usar xpath con BeautifulSoup?
- 9. podemos usar CASE con EXEC
- 10. Cómo podemos usar @ font-face en Menos
- 11. ¿Podemos usar git-cvs en Windows?
- 12. ¿Podemos usar datos JSON personalizados en cubismo?
- 13. ¿Podemos usar Foundation con HTML5Boilerplate?
- 14. ¿Qué podemos usar en lugar de nstimer?
- 15. ¿Podemos usar el ORM en GAE con Django ahora?
- 16. ¿Por qué no podemos usar uniones externas en CTE recursivo?
- 17. Cómo usar la unión en zend db
- 18. ¿Cómo usar la unión cruzada en el acceso?
- 19. ¿Podemos usar hilo dentro de [STAThread] principal?
- 20. podemos usar partido para comprobar el tipo de una clase
- 21. ¿Podemos usar $ (esto) con otro selector?
- 22. ¿Cómo podemos usar MSHTML con VBA?
- 23. ¿Podemos usar un ScrollView dentro de LinearLayout?
- 24. ¿Por qué usar id cuando podemos usar NSObject?
- 25. ¿Cómo podemos usar canales en Go en lugar de mutex?
- 26. ¿Cómo cambiar el puntero del mouse al puntero del dedo en el swing?
- 27. ¿Qué es mejor ... unión externa izquierda o unión externa derecha?
- 28. ¿Cómo podemos encontrar el TAMAÑO DE MEMORIA del puntero de memoria dado?
- 29. uso de doble puntero en lugar de puntero único
- 30. ¿Podemos usar JSch para la comunicación basada en claves SSH?
Las uniones no son para guardar memoria: expresan un * tipo de suma *, es decir. un tipo que contiene, por ejemplo. * cualquiera * un flotante * o * un int. Los sindicatos son difíciles de usar y bastante limitados. Por favor considere usar 'boost :: variant' en su lugar. –
Me temo que tengo que estar en desacuerdo con casi todo eso, @Alexandre :-) Ellos _son_ (incluso ahora) útiles para salvar la memoria, especialmente en el mundo pequeño integrado. No son difíciles de usar si comprendes el diseño subyacente (incluidas las debilidades definidas por la implementación) y hasta que alguien aumente los puertos a C (verifica las etiquetas), el tipo de variante no va a ser de mucha utilidad :-) – paxdiablo
Me olvidé 1) que era C 2) que las personas necesitan estar cerca del hardware a veces. Sin embargo, mi punto es que las uniones (en C++) no deberían usarse para representar tipos de suma. –