variable examples enum c struct unions

enum - unions in c examples



Diferencia entre una estructura y una uniĆ³n. (15)

¿Hay algún buen ejemplo para dar la diferencia entre una struct y una union ? Básicamente, sé que struct usa toda la memoria de sus miembros y union usa el espacio de memoria de miembros más grande. ¿Hay alguna otra diferencia de nivel de sistema operativo?


" union " y " struct " son construcciones del lenguaje C. Hablar de una diferencia de "nivel de SO" entre ellos es inapropiado, ya que es el compilador el que produce un código diferente si usa una u otra palabra clave.


¿Cuál es la diferencia entre estructura y unión?

La respuesta abreviada es: La deferencia está en la asignación de memoria. Explicación: en la estructura, se creará espacio de memoria para todos los miembros dentro de la estructura. En la memoria de unión, el espacio se creará solo para un miembro que necesite el mayor espacio de memoria. Considere el siguiente código:

struct s_tag { int a; long int b; } x; union u_tag { int a; long int b; } y;

Aquí hay dos miembros dentro de struct y union: int y long int. El espacio de memoria para int es: 4 bytes y el espacio de memoria para int largo es: 8 en el sistema operativo de 32 bits.

Así que para struct 4 + 8 = se crearán 12 bytes, mientras que se crearán 8 bytes para la unión

Ejemplo de código:

#include<stdio.h> struct s_tag { int a; long int b; } x; union u_tag { int a; long int b; } y; int main() { printf("Memory allocation for structure = %d", sizeof(x)); printf("/nMemory allocation for union = %d", sizeof(y)); return 0; }

Ref: http://www.codingpractise.com/home/c-programming/structure-and-union/


Aquí está la respuesta corta: una estructura es una estructura de registro: cada elemento de la estructura asigna un nuevo espacio. Por lo tanto, una estructura como

struct foobarbazquux_t { int foo; long bar; double baz; long double quux; }

asigna al menos (sizeof(int)+sizeof(long)+sizeof(double)+sizeof(long double)) bytes en memoria para cada instancia. ("Al menos" porque las restricciones de alineación de la arquitectura pueden obligar al compilador a rellenar la estructura).

Por otra parte,

union foobarbazquux_u { int foo; long bar; double baz; long double quux; }

asigna una porción de memoria y le da cuatro alias. Por lo tanto, sizeof(union foobarbazquux_u) ≥ max((sizeof(int),sizeof(long),sizeof(double),sizeof(long double)) , nuevamente con la posibilidad de algunas adiciones para alineaciones.


Como ya ha dicho en su pregunta, la principal diferencia entre union y struct es que union miembros de la union superponen la memoria de los demás, de modo que el tamaño de una unión es la única, mientras que los miembros de la struct se disponen uno tras otro (con relleno opcional). entre). Además, una unión es lo suficientemente grande como para contener a todos sus miembros y tiene una alineación que se ajusta a todos sus miembros. Así que digamos que int solo se puede almacenar en direcciones de 2 bytes y tiene 2 bytes de ancho, y long solo se puede almacenar en direcciones de 4 bytes y que tiene 4 bytes de longitud. La siguiente union

union test { int a; long b; };

podría tener un sizeof de 4 y un requisito de alineación de 4. Tanto una unión como una estructura pueden tener relleno al final, pero no al principio. Escribir en una estructura cambia solo el valor del miembro escrito. Escribir a un miembro de un sindicato hará que el valor de todos los demás miembros sea inválido. No puede acceder a ellos si no los ha escrito antes; de lo contrario, el comportamiento no está definido. GCC proporciona como una extensión que puede leer de miembros de un sindicato, aunque no haya escrito más recientemente. Para un sistema operativo, no tiene que importar si un programa de usuario escribe en una unión o en una estructura. Esto en realidad es sólo un problema del compilador.

Otra propiedad importante de union y struct es que permiten que un puntero a ellos pueda apuntar a tipos de cualquiera de sus miembros . Entonces lo siguiente es válido:

struct test { int a; double b; } * some_test_pointer;

some_test_pointer puede apuntar a int* o bool* . Si emite una dirección de tipo test a int* , apuntará a su primer miembro, a , en realidad. Lo mismo es cierto para una unión también. Por lo tanto, debido a que una unión siempre tendrá la alineación correcta, puede usar una unión para hacer que el apuntar a algún tipo sea válido:

union a { int a; double b; };

Esa unión será capaz de señalar un int, y un doble:

union a * v = (union a*)some_int_pointer; *some_int_pointer = 5; v->a = 10; return *some_int_pointer;

es realmente válido, según lo establecido por el estándar C99:

Un objeto tendrá acceso a su valor almacenado solo por una expresión lvalue que tenga uno de los siguientes tipos:

  • Un tipo compatible con el tipo efectivo del objeto.
  • ...
  • un tipo agregado o de unión que incluye uno de los tipos mencionados anteriormente entre sus miembros

El compilador no optimizará la v->a = 10; ya que podría afectar el valor de *some_int_pointer (y la función devolverá 10 lugar de 5 ).


Con una unión, solo se supone que debes usar uno de los elementos, porque todos están almacenados en el mismo lugar. Esto lo hace útil cuando desea almacenar algo que podría ser uno de varios tipos. Una estructura, por otro lado, tiene una ubicación de memoria separada para cada uno de sus elementos y todos se pueden usar a la vez.

Para dar un ejemplo concreto de su uso, hace un tiempo estaba trabajando en un intérprete de Scheme y básicamente estaba superponiendo los tipos de datos de Scheme a los tipos de datos de C. Esto implicaba almacenar en una estructura una enumeración que indicaba el tipo de valor y una unión para almacenar ese valor.

union foo { int a; // can''t use both a and b at once char b; } foo; struct bar { int a; // can use both a and b simultaneously char b; } bar; union foo x; x.a = 3; // OK x.b = ''c''; // NO! this affects the value of x.a! struct bar y; y.a = 3; // OK y.b = ''c''; // OK

edit: si se pregunta qué configuración de xb en ''c'' cambia el valor de xa, técnicamente hablando no está definido. En la mayoría de las máquinas modernas, un char es de 1 byte y un int es de 4 bytes, por lo que al dar a xb el valor ''c'' también le da al primer byte de xa el mismo valor:

union foo x; x.a = 3; x.b = ''c''; printf("%i, %i/n", x.a, x.b);

huellas dactilares

99, 99

¿Por qué los dos valores son iguales? Debido a que los últimos 3 bytes del int 3 son todos cero, entonces también se lee como 99. Si colocamos un número mayor para xa, verá que esto no siempre es así:

union foo x; x.a = 387439; x.b = ''c''; printf("%i, %i/n", x.a, x.b);

huellas dactilares

387427, 99

Para ver más de cerca los valores reales de la memoria, establezcamos e imprimamos los valores en hexadecimal:

union foo x; x.a = 0xDEADBEEF; x.b = 0x22; printf("%x, %x/n", x.a, x.b);

huellas dactilares

deadbe22, 22

Usted puede ver claramente donde el 0x22 sobrescribió el 0xEF.

PERO

En C, el orden de los bytes en un int no está definido. Este programa sobrescribió el 0xEF con 0x22 en mi Mac, pero hay otras plataformas en las que sobrescribiría el 0xDE porque el orden de los bytes que forman el int se invirtió. Por lo tanto, al escribir un programa, nunca debe confiar en el comportamiento de sobrescribir datos específicos en una unión porque no es portátil.

Para obtener más información sobre el orden de los bytes, echa un vistazo a endianness .


La estructura es una colección de diferentes tipos de datos donde diferentes tipos de datos pueden residir en ella y cada uno tiene su propio bloque de memoria.

por lo general, usamos union cuando estamos seguros de que solo una de las variables se usará a la vez y usted desea una utilización completa de la memoria actual porque obtiene solo un bloque de memoria que es igual al tipo más grande.

struct emp { char x;//1 byte float y; //4 byte } e;

memoria total se obtiene => 5 bytes

union emp { char x;//1 byte float y; //4 byte } e;

memoria total se obtiene = 4 bytes


Lo tienes, eso es todo. Pero entonces, básicamente, ¿para qué sirven los sindicatos?

Puedes poner en la misma ubicación contenido de diferentes tipos. Debe saber el tipo de lo que ha almacenado en la unión (por lo tanto, a menudo lo coloca en una struct con una etiqueta de tipo ...).

¿Porque es esto importante? Realmente no para ganar espacio. Sí, puedes ganar algunos bits o hacer algo de relleno, pero ese ya no es el punto principal.

Es para la seguridad de tipos, le permite hacer algún tipo de ''escritura dinámica'': el compilador sabe que su contenido puede tener diferentes significados y el significado preciso de cómo lo interpreta usted depende de usted en tiempo de ejecución. Si tiene un puntero que puede apuntar a diferentes tipos, DEBE usar una unión; de lo contrario, el código puede ser incorrecto debido a problemas de alias (el compilador se dice a sí mismo "oh, solo este puntero puede apuntar a este tipo, así que puedo optimizar fuera de esos accesos ... ", y pueden pasar cosas malas).


Los sindicatos son útiles al escribir una función de ordenamiento de bytes que se muestra a continuación. No es posible con las estructuras.

int main(int argc, char **argv) { union { short s; char c[sizeof(short)]; } un; un.s = 0x0102; if (sizeof(short) == 2) { if (un.c[0] == 1 && un.c[1] == 2) printf("big-endian/n"); else if (un.c[0] == 2 && un.c[1] == 1) printf("little-endian/n"); else printf("unknown/n"); } else printf("sizeof(short) = %d/n", sizeof(short)); exit(0); } // Program from Unix Network Programming Vol. 1 by Stevens.


Los usos de las uniones sindicales se utilizan con frecuencia cuando se necesitan conversaciones de tipo especializado. Para tener una idea de la utilidad de la unión. La biblioteca estándar de c / c no define ninguna función específicamente diseñada para escribir enteros cortos en un archivo. El uso de fwrite () genera una sobrecarga excesiva para una operación simple. Sin embargo, al usar una unión, puede crear fácilmente una función que escribe un binario de un entero corto en un archivo de un byte a la vez. Supongo que los enteros cortos son de 2 bytes de longitud

EL EJEMPLO:

#include<stdio.h> union pw { short int i; char ch[2]; }; int putw(short int num, FILE *fp); int main (void) { FILE *fp; fp fopen("test.tmp", "wb "); putw(1000, fp); /* write the value 1000 as an integer*/ fclose(fp); return 0; } int putw(short int num, FILE *fp) { pw word; word.i = num; putc(word.c[0] , fp); return putc(word.c[1] , fp); }

aunque putw () llamé con un entero corto, era posible usar putc () y fwrite (). Pero quería mostrar un ejemplo para dominar cómo se puede usar una unión


Sí, la principal diferencia entre estructura y unión es la misma que usted indicó. Struct usa toda la memoria de sus miembros y union usa el espacio de memoria de miembros más grande.

Pero toda la diferencia radica en la necesidad de uso de la memoria. El mejor uso de la unión se puede ver en los procesos de Unix donde hacemos uso de señales. como un proceso puede actuar sobre una sola señal a la vez. Así que la declaración general será:

union SIGSELECT { SIGNAL_1 signal1; SIGNAL_2 signal2; ..... };

En este caso, el proceso utiliza solo la memoria más alta de todas las señales. pero si usa struct en este caso, el uso de la memoria será la suma de todas las señales. Hace mucha diferencia

Para resumir, debe seleccionarse Unión si sabe que accede a cualquiera de los miembros a la vez.


Técnicamente no hablando significa:

Supuesto: silla = bloque de memoria, personas = variable

Estructura : Si hay 3 personas pueden sentarse en silla de su tamaño correspondiente.

Unión : si hay 3 personas, solo habrá una silla para sentarse, todas necesitan usar la misma silla cuando quieran sentarse.

Técnicamente hablando significa:

El programa mencionado a continuación ofrece una profunda inmersión en la estructura y la unión.

struct MAIN_STRUCT { UINT64 bufferaddr; union { UINT32 data; struct INNER_STRUCT{ UINT16 length; UINT8 cso; UINT8 cmd; } flags; } data1; };

Tamaño total de MAIN_STRUCT = sizeof (UINT64) para bufferaddr + sizeof (UNIT32) para union + 32 bit para el relleno (depende de la arquitectura del procesador) = 128 bits. Para la estructura todos los miembros obtienen el bloque de memoria de forma contigua.

Union obtiene un bloque de memoria del miembro de tamaño máximo (aquí su 32 bits). Dentro de la unión se encuentra una estructura más (INNER_STRUCT) sus miembros obtienen un bloque de memoria de tamaño total de 32 bits (16 + 8 + 8). En la unión se puede acceder al miembro INNER_STRUCT (32 bits) o a los datos (32 bits).


Una union es útil en un par de escenarios. union puede ser una herramienta para la manipulación de muy bajo nivel, como escribir controladores de dispositivo para un kernel.

Un ejemplo de esto es la disección de un número float mediante el uso de la union de una struct con campos de bits y un float . Guardo un número en el float , y luego puedo acceder a partes particulares del float través de esa struct . El ejemplo muestra cómo se usa la union para tener diferentes ángulos para mirar los datos.

#include <stdio.h> union foo { struct float_guts { unsigned int fraction : 23; unsigned int exponent : 8; unsigned int sign : 1; } fg; float f; }; void print_float(float f) { union foo ff; ff.f = f; printf("%f: %d 0x%X 0x%X/n", f, ff.fg.sign, ff.fg.exponent, ff.fg.fraction); } int main(){ print_float(0.15625); return 0; }

Eche un vistazo a la descripción de precisión simple en wikipedia. Usé el ejemplo y el número mágico 0.15625 de allí.

union también se puede usar para implementar un tipo de datos algebraico que tiene múltiples alternativas. Encontré un ejemplo de eso en el libro "Real World Haskell" de O''Sullivan, Stewart y Goerzen. Échale un vistazo en la sección El sindicato discriminado .

¡Aclamaciones!


Una Unión es diferente de una estructura, ya que una Unión se repite sobre las demás: redefine la misma memoria, mientras que la estructura define una tras otra sin superposiciones ni redefiniciones.


Una estructura asigna el tamaño total de todos los elementos en ella.

Una unión solo asigna tanta memoria como su miembro más grande requiere.


¿Hay algún buen ejemplo para dar la diferencia entre una ''estructura'' y una ''unión''?

Un protocolo de comunicaciones imaginario.

struct packetheader { int sourceaddress; int destaddress; int messagetype; union request { char fourcc[4]; int requestnumber; }; };

En este protocolo imaginario, se ha determinado que, según el "tipo de mensaje", la siguiente ubicación en el encabezado será un número de solicitud o un código de cuatro caracteres, pero no ambos. En resumen, las uniones permiten que la misma ubicación de almacenamiento represente más de un tipo de datos, donde se garantiza que solo deseará almacenar uno de los tipos de datos a la vez.

Los sindicatos son en gran medida un detalle de bajo nivel basado en la herencia de C como un lenguaje de programación del sistema, donde las ubicaciones de almacenamiento "superpuestas" a veces se usan de esta manera. En ocasiones, puede usar uniones para guardar la memoria donde tiene una estructura de datos donde solo se guardará uno de varios tipos al mismo tiempo.

En general, el sistema operativo no le importa ni sabe acerca de estructuras y uniones, ambos son simplemente bloques de memoria. Una estructura es un bloque de memoria que almacena varios objetos de datos, donde esos objetos no se superponen. Una unión es un bloque de memoria que almacena varios objetos de datos, pero tiene solo almacenamiento para el más grande de estos, y por lo tanto solo puede almacenar uno de los objetos de datos en cualquier momento.