initialization ¿cuál - Cómo inicializar una estructura de acuerdo con los estándares del lenguaje de programación C




c? estructuras (12)

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

typedef struct MY_TYPE {
  boolean 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 funciona?

Actualización terminé teniendo un elemento de inicialización estático donde configuré cada subelemento de acuerdo con mis necesidades.


Answers

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 };

No me gustó ninguna de estas respuestas, así que hice las mías. No sé si esto es ANSI C o no, es solo GCC 4.2.1 en su modo predeterminado. Nunca puedo recordar el paréntesis, así que comienzo con un subconjunto de mis datos y lucho contra los mensajes de error del compilador hasta que se cierra. La legibilidad es mi primera prioridad.

    // in a header:
    typedef unsigned char uchar;

    struct fields {
      uchar num;
      uchar lbl[35];
    };

    // in an actual c file (I have 2 in this case)
    struct fields labels[] = {
      {0,"Package"},
      {1,"Version"},
      {2,"Apport"},
      {3,"Architecture"},
      {4,"Bugs"},
      {5,"Description-md5"},
      {6,"Essential"},
      {7,"Filename"},
      {8,"Ghc-Package"},
      {9,"Gstreamer-Version"},
      {10,"Homepage"},
      {11,"Installed-Size"},
      {12,"MD5sum"},
      {13,"Maintainer"},
      {14,"Modaliases"},
      {15,"Multi-Arch"},
      {16,"Npp-Description"},
      {17,"Npp-File"},
      {18,"Npp-Name"},
      {19,"Origin"}
    };

Los datos pueden comenzar como un archivo delimitado por tabulaciones que busca y reemplaza para masajearlo en otra cosa. Sí, esto es Debian. Entonces, un par externo de {} (que indica la matriz), luego otro par para cada estructura interna. Con comas entre. Poner las cosas en un encabezado no es estrictamente necesario, pero tengo aproximadamente 50 elementos en mi estructura, así que los quiero en un archivo separado, tanto para mantener el desorden de mi código como para que sea más fácil de reemplazar.


void function(void) {
  MY_TYPE a;
  a.flag = true;
  a.value = 15;
  a.stuff = 0.123;
}

Veo que ya recibió una respuesta sobre ANSI C 99, así que le diré algo sobre ANSI C 89. ANSI C 89 le permite iniciar 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;
}

Algo 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 de basura".

¡Buena suerte!


En (ANSI) C99, puede usar un inicializador designado para inicializar una estructura:

MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };

Edición: Los otros miembros se inicializan como cero: "Los miembros de campo omitidos se inicializan implícitamente igual que los objetos que tienen una duración de almacenamiento estático". ( https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html )


a = (MYTYPE){ true, 15, 0.123 };

haría bien en C99


He leído la documentación de Microsoft Visual Studio 2015 para inicializar tipos agregados , sin embargo, todas las formas de inicialización con {...} se explican allí, pero la inicialización con punto, denominada "designador" no se menciona allí. No funciona también.

La inicialización del capítulo 6.7.8 de C99 explica la posibilidad de los designadores, pero en mi opinión no está muy claro para estructuras complejas. El estándar C99 como pdf .

En mi mente, puede ser mejor

  1. Utilice el = {0}; -inicialización para todos los datos estáticos. Es menos esfuerzo para el código máquina.
  2. Usa macros para inicializar, por ejemplo

    typedef MyStruct_t{ int x, int a, int b; } MyStruct; define INIT_MyStruct(A,B) { 0, A, B}

La macro se puede adaptar, su lista de argumentos puede ser independiente del contenido de la estructura modificada. Es correcto si se deben inicializar menos elementos. También es apropiado para estructuras anidadas. 3. Una forma simple es: Inicializar en una subrutina:

void init_MyStruct(MyStruct* thiz, int a, int b) {
  thiz->a = a; thiz->b = b; }

Esta rutina se parece a ObjectOriented en C. ¡Usa thiz , no this para compilarlo también con C ++!

MyStruct data = {0}; //all is zero!
init_MyStruct(&data, 3, 456);

Si MS no se ha actualizado a C99, MY_TYPE a = {true, 15,0.123};


Encontré otra forma de inicializar estructuras.

La estructura:

typedef struct test {
    int num;
    char* str;
} test;

Inicialización:

test tt = {
    num: 42,
    str: "nice"
};

Según la documentación de GCC, esta sintaxis está https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html .


El estándar de lenguaje de programación C ISO / IEC 9899: 1999 (comúnmente conocido como C99) permite utilizar un inicializador designado para inicializar miembros de una estructura o unión de la siguiente manera:

MY_TYPE a = { .stuff = 0.456, .flag = true, .value = 123 };

Se define en el paragraph 7 , sección 6.7.8 Initialization de la norma ISO / IEC 9899: 1999 como:

Si un designador tiene la forma
. identificador
entonces el objeto actual (definido abajo) tendrá estructura o tipo de unión y el identificador será el nombre de un miembro de ese tipo.

Tenga en cuenta que el paragraph 9 de la misma sección establece que:

Excepto cuando se indique explícitamente lo contrario, para los fines de esta subcláusula, los miembros sin nombre de los objetos de estructura y tipo de unión no participan en la inicialización. Los miembros sin nombre de los objetos de estructura tienen un valor indeterminado incluso después de la inicialización.

En la implementación de GNU GCC, sin embargo, los miembros omitidos se inicializan como cero o como valores de tipo de tipo apropiado. Como se indica en la sección https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html de la documentación de GNU GCC:

Los miembros de campo omitidos se inicializan implícitamente igual que los objetos que tienen una duración de almacenamiento estático.

El compilador de Microsoft Visual C ++ debe admitir los inicializadores designados desde la versión 2013 de acuerdo con la publicación oficial del blog C ++ Conformance Roadmap . El artículo sobre Initializing unions and structs de Initializers en la documentación de MSDN Visual Studio sugiere que los miembros sin nombre se inicializaron con valores apropiados similares a cero de manera similar a GNU GCC.

La nueva norma ISO / IEC 9899: 2011 (comúnmente conocida como C11) que había reemplazado a ISO / IEC 9899: 1999 conserva los inicializadores designados en la sección 6.7.9 Initialization . También conserva el paragraph 9 sin cambios.


La estructura en C se puede declarar e inicializar así:

typedef struct book
{
    char title[10];
    char author[10];
    float price;
} book;

int main() {
    book b1={"DS", "Ajay", 250.0};

    printf("%s \t %s \t %f", b1.title, b1.author, b1.price);

    return 0;
}

Hay una taquigrafía que utilizo que no es muy eficiente en el tiempo, pero se ajusta a una sola línea:

Set<String> h = new HashSet<>(Arrays.asList("a", "b"));

Nuevamente, esto no es eficiente en el tiempo ya que está construyendo una matriz, convirtiéndose en una lista y utilizando esa lista para crear un conjunto.

Al inicializar conjuntos finales estáticos, normalmente lo escribo así:

public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));

Un poco menos feo y la eficiencia no importa para la inicialización estática.







c struct initialization