Cómo inicializar una estructura de acuerdo con los estándares del lenguaje de programación C

7 minutos de lectura

avatar de usuario
morir de vergüenza

Quiero inicializar un elemento de estructura, dividirlo en declaración e inicialización. Esto es lo que tengo:

typedef struct MY_TYPE {
  bool flag;
  short int value;
  double stuff;
} MY_TYPE;

void function(void) {
  MY_TYPE a;
  ...
  a = { true, 15, 0.123 }
}

¿Es esta la forma de declarar e inicializar una variable local de MY_TYPE de acuerdo con los estándares del lenguaje de programación C (C89, C90, C99, C11, etc.)? ¿O hay algo mejor o al menos que funcione?

Actualizar Terminé teniendo un elemento de inicialización estático donde configuré cada subelemento según mis necesidades.

  • realmente deberías aceptar una mejor respuesta, veo que tuviste que usar una mala guía de codificación, pero aún así no deberías sugerir a otras personas que esa es la forma correcta de hacerlo.

    –Karoly Horvath

    28 de julio de 2012 a las 9:43


  • @KarolyHorvath bueno, la mayoría de las buenas respuestas son específicas de C99. ¿Quizás mi pregunta es un duplicado de stackoverflow.com/questions/6624975/…?

    – morir de vergüenza

    29 de julio de 2012 a las 10:02

  • si esa era su intención original, entonces probablemente sí, pero luego 1) los votos serían muy engañosos. 2) de los principales resultados de búsqueda, este es el único que muestra la forma C99… sería mejor reutilizar esta página para la demostración C99… (aparentemente, la gente comenzó a vincular esta página para mostrar cómo hazlo)

    –Karoly Horvath

    29 de julio de 2012 a las 11:02


  • Es interesante que la respuesta aceptada (y fuertemente votada) en realidad no responda la pregunta, incluso como se publicó originalmente. Los inicializadores designados no abordan el problema del OP, que es separar la declaración de la inicialización. Para C anterior a 1999, la única solución real es asignar a cada miembro; para C99 y posteriores, un literal compuesto, como en la respuesta de CesarB, es la solución. (Por supuesto, un inicializador real, con o sin designadores, sería aún mejor, pero aparentemente el OP estaba cargado con un estándar de codificación realmente malo).

    –Keith Thompson

    9 de junio de 2013 a las 6:39

  • Estrictamente hablando, el término “ANSI C” ahora se refiere a la norma ISO de 2011, que ANSI ha adoptado. Pero en la práctica, el término “ANSI C” comúnmente se refiere al estándar (oficialmente obsoleto) de 1989. Por ejemplo, “gcc -ansi” aún aplica el estándar de 1989. Dado que es ISO la que publicó los estándares de 1990, 1999 y 2011, es mejor evitar el término “ANSI C” y referirse a la fecha del estándar si existe alguna posibilidad de confusión.

    –Keith Thompson

    9 de junio de 2013 a las 6:43

avatar de usuario
cesarb

Puedes hacerlo con un literal compuesto. Según esa página, funciona en C99 (que también cuenta como ANSI C).

MY_TYPE a;

a = (MY_TYPE) { .flag = true, .value = 123, .stuff = 0.456 };
...
a = (MY_TYPE) { .value = 234, .stuff = 1.234, .flag = false };

Las designaciones en los inicializadores son opcionales; también podrías escribir:

a = (MY_TYPE) { true,  123, 0.456 };
...
a = (MY_TYPE) { false, 234, 1.234 };

  • Entonces, ¿los inicializadores designados son para cuando declara y define al mismo tiempo, pero los literales compuestos son para cuando define una variable ya declarada?

    – Geremia

    24 de marzo de 2016 a las 19:09

  • @Geremia, primero debe definir la estructura en ambos casos, pero con inicializadores designados, hace que el código sea más legible y más resistente a los errores, en caso de cambios en la estructura.

    – hoijui

    18 de diciembre de 2017 a las 7:05

  • Esto es un poco complicado. Muchas veces (algunas con éxito) he intentado usar inicializadores designados. Sin embargo, solo ahora ha quedado claro (gracias a su ejemplo y el de @philant) que debe existir una conversión si el inicializador no se usa en el momento de la creación del objeto. Sin embargo, ahora también aprendí que si los inicializadores se usan en un momento que no sea la creación de objetos (como en su ejemplo), se lo conoce como un literal compuestono estrictamente un inicializador designado. ideone.com/Ze3rnZ

    – sherrellbc

    28 de diciembre de 2017 a las 12:23


avatar de usuario
ron nuni

Veo que ya recibiste una respuesta sobre ANSI C 99, por lo que lanzaré un hueso sobre ANSI C 89. ANSI C 89 te permite inicializar una estructura de esta manera:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = { 5, 2.2, "George" };
    return 0;
}

Una cosa importante para recordar, en el momento en que inicializa incluso un objeto/variable en la estructura, todas sus otras variables se inicializarán al valor predeterminado.

Si no inicializa los valores en su estructura, todas las variables contendrán “valores basura”.

¡Buena suerte!

  • ¿Es posible utilizar variables en la inicialización?

    – Cian

    20 mayo 2016 a las 13:47

  • @Cyan Es para objetos con duración de almacenamiento automático. Ver 6.7.9 13) en open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf . Para los objetos globales está bastante restringido a los literales. Ni siquiera puede usar otros objetos globales, incluso si son constantes.

    – PSkocik

    9 oct 2016 a las 11:47

  • Entonces, ¿la única diferencia con C 99 es que no puede especificar las designaciones?

    – Akaisteph7

    24 de febrero de 2020 a las 23:55

avatar de usuario
Neuron – Libertad para Ucrania

Como dijo Ron Nuni:

typedef struct Item {
    int a;
    float b;
    char* name;
} Item;

int main(void) {
    Item item = {5, 2.2, "George"};
    return 0;
}

Una cosa importante para recordar: en el momento en que inicializa incluso un objeto/variable en la estructura, todas sus otras variables se inicializarán al valor predeterminado.

Si no inicializa los valores en su estructura (es decir, si solo declara esa variable), todo variable.members contendrá “valores basura”, ¡solo si la declaración es local!

Si la declaración es global o estático (como en este caso), todos sin inicializar variable.members se inicializará automáticamente a:

  • 0 para enteros y punto flotante
  • '\0' por char (por supuesto, esto es lo mismo que 0y char es un tipo entero)
  • NULL para punteros.

  • ¿Es posible utilizar variables en la inicialización?

    – Cian

    20 mayo 2016 a las 13:47

  • @Cyan Es para objetos con duración de almacenamiento automático. Ver 6.7.9 13) en open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf . Para los objetos globales está bastante restringido a los literales. Ni siquiera puede usar otros objetos globales, incluso si son constantes.

    – PSkocik

    9 oct 2016 a las 11:47

  • Entonces, ¿la única diferencia con C 99 es que no puede especificar las designaciones?

    – Akaisteph7

    24 de febrero de 2020 a las 23:55

avatar de usuario
Neuron – Libertad para Ucrania

ya casi lo tienes…

MY_TYPE a = { true, 15, 0.123 };

Rápido busque en ‘struct initialize c’ me muestra esto

  • Creo que esto es cierto para el estándar C, pero no para ANSI C (99?). Además, estoy sujeto a reglas de codificación que no me permiten hacer la declaración y la inicialización a la vez, por lo que tengo que dividirlo e inicializar cada uno de los subelementos.

    – morir de vergüenza

    1 de diciembre de 2008 a las 13:26

  • La inicialización solo puede ocurrir en el punto de declaración. Eso es lo que significa ‘inicializar’. De lo contrario, está permitiendo que un valor indefinido sea el valor inicial de su variable/estructura, y luego asignando un valor más adelante.

    – Kieveli

    1 de diciembre de 2008 a las 13:43

  • um… ¿Tienes reglas de codificación que son deliberadamente malas? Tal vez debería presentarle al tipo que los escribió “Adquisición de recursos es inicialización” (en.wikipedia.org/wiki/RAII)

    – James Curran

    1 de diciembre de 2008 a las 15:10

  • Confía en mí, realmente, realmente, no puedo cambiar ni un poco de estas reglas en este momento. Se siente horrible codificarlo. Y hay muchas otras reglas de los años 70, como encabezados de código estáticos con información de administración como el número de revisión. Cambios para cada lanzamiento, incluso si la fuente no cambió…

    – morir de vergüenza

    2 de diciembre de 2008 a las 7:12

¿Ha sido útil esta solución?