Inicialización de unión en programación C y olor a código

Inicialización de unión en programación C y olor a código

En esta publicación de blog, aprenderá todos los conceptos importantes relacionados con la inicialización de unión en la programación C. Aquí no explicaremos el concepto de la unión en C. Solo explicaremos la forma y los problemas relacionados con la unión C.

Las publicaciones del blog cubren los siguientes temas:

  • ¿Cómo se inicializa una unión en C o Inicialización de unión en C?
  • ¿Cuántos miembros del sindicato se pueden inicializar?
  • ¿Inicializadores designados de una unión en C?
  • El error que se puede generar con los inicializadores de unión.

¿Cómo se inicializa la unión en C:

?

Antes de comprender cómo inicializar una unión, comprendamos el significado de inicialización.

En programación C, la inicialización es la asignación de un valor inicial para una variable (objeto). La forma de inicializar un objeto depende del lenguaje de programación, así como de su tipo, clase de almacenamiento, etc. Normalmente, la inicialización se realiza mediante inicializadores y listas de inicializadores.

Considere el siguiente ejemplo,

static int data1;   // initializes data1 to 0

int data2 = 1;      // initializes data2 to 1

// initializes int arr[4] to 1,3,5,25
int arr[] = { 1, 3, 5, 25 };

Ahora creo que tiene una comprensión básica de la inicialización, así que pasemos a nuestro tema inicialización de la unión.

Al igual que otros inicializadores, un inicializador de unión especifica el valor inicial almacenado en un objeto de unión. Al inicializar un objeto de tipo unión, el inicializador debe ser una lista no vacía, (hasta C23), entre llaves, separada por comas de inicializadores para los miembros.

Los siguientes son los inicializadores de la unión.

1.)  = { expression , ... }

2.) = { designator expression , ... } (desde C99)

3.) = { } (desde C23)

Analicemos cada inicializador de unión uno por uno con un código de ejemplo.

1. lista de inicializadores:

Al inicializar una unión, la lista de inicializadores debe tener solo un miembro (hasta C23), que inicializa el primer miembro de la unión.

Tomemos un ejemplo para una mejor comprensión.

#include <stdio.h>
union Test
{
    int x;
    char c;
};


int main()
{
    union Test obj = {1};

    printf("%d\n", obj.x);

    return 0;
}

Output: 1

2. Inicializadores designados (Desde C99):

Usando el designador podemos inicializar el miembro específico de una unión. El designador tiene la forma .identifier . Aquí identificador es el nombre de un miembro del tipo de sindicato dado.

La siguiente sintaxis puede inicializar cualquier miembro de una unión:

union Test
{
    /*
      List of union members

    */
};


//union object
union Test obj = {.any_member = 42 };

También puede usar el designador con una unión sin unión de etiquetas (nombrada, pero no etiquetada).

union
{
    /* 
      List of union members 
    
    */
} obj = {.any_member = 42 };

Considere el siguiente ejemplo,

#include <stdio.h>


union Test
{
    int i;
    double d;
};

int main()
{
    //Initialization
    union Test temp = { .d = 4 };

    printf("%f\n", temp.d);

    return 0;
}

Output: 4.000000

3. inicializador vacío (C23):

Un par de llaves vacío ({} ) se denomina inicializador vacío y se denomina inicialización vacía. Se introduce en C23.

Considere el siguiente ejemplo,

#include <stdio.h>

union Test
{
    int i;
    double d;
};

int main()
{
    //empty Initialization C23
    union Test temp = {};

    printf("%d\n", temp.i);

    return 0;
}

Output: 0

Una pregunta debe venir a su mente cuál será el valor de un objeto que se inicializa con un inicializador vacío.

No te preocupes, C23 ya ha dado la respuesta a esta pregunta.

Entonces, si un objeto se inicializa con un inicializador vacío, entonces:

  • El tipo de puntero se inicializa como un puntero nulo.
  • Los tipos integrales se inicializan a cero sin signo.
  • Los tipos flotantes decimales se inicializan en cero positivo y el exponente cuántico está definido por la implementación.
  • Todos los elementos de los arreglos, todos los miembros de las estructuras y los primeros miembros de las uniones se inicializan de acuerdo con las reglas anteriores, de forma recursiva, además de que todos los bits de relleno se inicializan a cero.

Inicialización de unión anónima:

Un miembro sin nombre cuyo especificador de tipo es un especificador de unión sin etiqueta se denomina unión anónima. Sus miembros también se consideran miembros de la estructura o unión contenedora, conservando su estructura o disposición de unión. Y esto se aplica recursivamente si la estructura contenedora o unión también es anónima.

El siguiente ejemplo ilustra uniones anónimas:

struct Test
{
    union   // anonymous union
    {
        int var1;
        char var2;
    };
    int data;
} obj;

Dado que los miembros de uniones anónimas se consideran miembros de la estructura contenedora
o unión, la estructura Prueba del siguiente ejemplo tiene tres miembros. Podemos acceder a var1 y var2 usando el objeto de struct Test.

Aquí estoy interesado en explicar cómo puede inicializar miembros de unión anónimos de una estructura. Tomemos un ejemplo para una mejor comprensión.

#include <stdio.h>

struct Test
{
    union   // anonymous union
    {
        int var1;
        char var2;
    };
    int data;
};

int main()
{
    struct Test obj = {{257}, 128};

    printf("obj.var1 = %d obj.data = %d\n",obj.var1, obj.data);
    
    return 0;
}

Salida:

obj.var1 = 257 obj.data = 128

Explicación: 

Puede ver el código de ejemplo anterior donde los miembros de la unión anónima se comportan como los miembros de la estructura.

Código olor:

Veamos algunos ejemplos de programas en C que no son un error del compilador pero que pueden presentar problemas graves.

Question-1:

#include <stdio.h>
union Test
{
    char a;
    int b;
};


int main()
{
    union Test obj = {127};

    printf("%d\n", obj.b);

    return 0;
}

Salida: Comportamiento no especificado

Explicación :

En el ejemplo anterior, estamos inicializando el primer miembro de la unión, lo que significa inicializar los miembros de datos 'a '. Pero estamos leyendo que ‘b ' que le da un valor no especificado.

Note: Si el miembro utilizado para leer el contenido de un objeto de unión no es el mismo que el último miembro utilizado para almacenar un valor en el objeto, la parte adecuada de la representación de objeto del valor se reinterpreta como una representación de objeto en el nuevo tipo ( un proceso a veces llamado "juego de palabras tipográfico"). Si el tamaño del nuevo tipo es mayor que el tamaño del último tipo escrito, el contenido de los bytes sobrantes no se especifica (y tal vez sea una representación de trampa).

Question-2:

#include <stdio.h>

struct Test
{
    int a;
    union   // anonymous union
    {
        char b;
        int c;
    };

};

int main()
{
    struct Test obj = {128, {257}};

    return 0;
}

Output: Y No obtendrá el resultado deseado.

Explanation:

Una lista de inicializadores de unión inicializa el primer miembro de la unión de la unión a menos que se utilice un inicializador designado. Porque en el ejemplo dado, el primer miembro de la unión se firma char cuyo rango es -128 a 127 y estamos tratando de inicializarlo con 257; Se producirá un desbordamiento porque 257 está fuera de su rango.

Publicación recomendada:

  • Cursos y tutoriales de programación en C.
  • Cursos y Tutoriales de Programación CPP.
  • Cursos y tutoriales de Python.
  • Aprenda las uniones C con la ayuda de un código de ejemplo.
  • Inicializadores designados en C. 
  • estructura en C:debes conocerla en profundidad
  • relleno de estructura en C, deberías saberlo.
  • ¿Qué es un miembro de matriz flexible en c?
  • ¿Cuál es la importancia de struct hack en c?
  • Cómo acceder al puntero dentro de una estructura en c.
  • ¿Cómo usar la estructura del puntero de función en lenguaje c?
  • Puntero de función en la estructura.
  • Las 10 principales preguntas de la entrevista sobre relleno de estructura.