Una estructura es un tipo que consta de una secuencia de miembros cuyo almacenamiento se asigna en una secuencia ordenada (a diferencia de la unión, que es un tipo que consta de una secuencia de miembros cuyo almacenamiento se superpone).

El especificador de tipo para una estructura es idéntico al union especificador de tipo excepto por la palabra clave utilizada:

Sintaxis

structnombre(Opcional) lista de declaraciones de estructura (1)
structnombre (2)

1) Definición de estructura: introduce la nueva estructura de tipo nombre y define su significado2) Si se usa en una línea propia, como en structnombre;, declara pero no define la estructura name (ver declaración de futuro a continuación). En otros contextos, nombra la estructura previamente declarada.

nombre el nombre de la estructura que se está definiendo
lista de declaraciones de estructura cualquier número de declaraciones de variables, declaraciones de campo de bits y declaraciones de aserción estática. Los miembros de tipo incompleto y los miembros de tipo de función no están permitidos (excepto para el miembro de matriz flexible que se describe a continuación)

Explicación

Dentro de un objeto de estructura, las direcciones de sus elementos (y las direcciones de las unidades de asignación de campo de bits) aumentan en el orden en que se definieron los miembros. Un puntero a una estructura se puede convertir a un puntero a su primer miembro (o, si el miembro es un campo de bits, a su unidad de asignación). Del mismo modo, un puntero al primer miembro de una estructura se puede convertir en un puntero a la estructura adjunta. Puede haber un relleno sin nombre entre dos miembros cualesquiera de una estructura o después del último miembro, pero no antes del primer miembro. El tamaño de una estructura es al menos tan grande como la suma de los tamaños de sus miembros.

Si una estructura define al menos un miembro con nombre, se le permite declarar adicionalmente su último miembro con un tipo de matriz incompleto. Cuando se accede a un elemento del miembro de matriz flexible (en una expresión que usa el operador . o -> con el nombre del miembro de la matriz flexible como el operando del lado derecho), entonces la estructura se comporta como si el miembro de la matriz tuviera el ajuste de tamaño más largo en la memoria asignada para este objeto. Si no se asignó almacenamiento adicional, se comporta como si se tratara de una matriz con 1 elemento, excepto que el comportamiento no está definido si se accede a ese elemento o si se produce un puntero uno más allá de ese elemento. Inicialización sizeofy el operador de asignación ignora el miembro de matriz flexible. Las estructuras con miembros de matriz flexibles (o uniones que tienen un miembro de estructura posiblemente recursivo con miembro de matriz flexible) no pueden aparecer como elementos de matriz o como miembros de otras estructuras.

structsint n;double d[];;// s.d is a flexible array member structs t1 =0;// OK, d is as if double d[1], but UB to accessstructs t2 =1,4.2;// error: initialization ignores flexible array// if sizeof (double) == 8structs*s1 =malloc(sizeof(structs)+64);// as if d was double d[8]structs*s2 =malloc(sizeof(structs)+40);// as if d was double d[5]
 
    s1 =malloc(sizeof(structs)+10);// now as if d was double d[1]. Two bytes excess.double*dp =&(s1->d[0]);// OK*dp =42;// OK
    s1->d[1]++;// Undefined behavior. 2 excess bytes can't be accessed // as double.
 
    s2 =malloc(sizeof(structs)+6);// same, but UB to access because 2 bytes are// missing to complete 1 double
    dp =&(s2->d[0]);//  OK, can take address just fine*dp =42;//  undefined behavior*s1 =*s2;// only copies s.n, not any element of s.d// except those caught in sizeof (struct s)
(desde C99)

Similar a union, un miembro sin nombre de una estructura cuyo tipo es una estructura sin nombre que se conoce como estructura anónima. Cada miembro de una estructura anónima se considera un miembro de la estructura o unión adjunta. Esto se aplica de forma recursiva si la estructura o unión adjunta también es anónima.

structvunion// anonymous unionstructint i, j;;// anonymous structurestructlong k, l; w;;int m; v1;
 
v1.i =2;// valid
v1.k =3;// invalid: inner structure is not anonymous
v1.w.k =5;// valid

De manera similar a la unión, el comportamiento del programa no está definido si la estructura se define sin ningún miembro con nombre (incluidos los obtenidos mediante uniones o estructuras anidadas anónimas).

(desde C11)

Declaración de reenvío

Una declaración de la siguiente forma.

structnombre;

oculta cualquier significado previamente declarado para el nombre nombre en el espacio del nombre de la etiqueta y declara nombre como un nuevo nombre de estructura en el alcance actual, que se definirá más adelante. Hasta que aparezca la definición, este nombre de estructura tiene un tipo incompleto.

Esto permite estructuras que se refieren entre sí:

structy;structxstructy*p;/* ... */;structystructx*q;/* ... */;

Tenga en cuenta que también se puede introducir un nuevo nombre de estructura simplemente usando una etiqueta de estructura dentro de otra declaración, pero si una estructura declarada previamente con el mismo nombre existe en el espacio de nombre de etiqueta, la etiqueta se referirá a ese nombre.

structs* p =NULL;// tag naming an unknown struct declares itstructsint a;;// definition for the struct pointed to by pvoidg(void)structs;// forward declaration of a new, local struct s// this hides global struct s until the end of this blockstructs*p;// pointer to local struct s// without the forward declaration above,// this would point at the file-scope sstructschar* p;;// definitions of the local struct s

Palabras clave

struct.

Notas

Consulte Inicialización de estructuras para conocer las reglas relacionadas con los inicializadores de estructuras.

Dado que no se permiten miembros de tipo incompleto y un tipo de estructura no está completo hasta el final de la definición, una estructura no puede tener un miembro de su propio tipo. Se permite un puntero a su propio tipo y se usa comúnmente para implementar nodos en listas o árboles vinculados.

Debido a que una declaración de estructura no establece el alcance, tipos anidados, enumeraciones y enumeradores introducidos por declaraciones dentro lista de declaraciones de estructura son visibles en el ámbito circundante donde se define la estructura.

Ejemplo

#include#includeintmain(void)structcarchar*make;char*model;int year;;// declares the struct type// declares and initializes an object of a previously-declared struct typestructcar c =.year=1923,.make="Nash",.model="48 Sports Touring Car";printf("car: %d %s %sn", c.year, c.make, c.model);// declares a struct type, an object of that type, and a pointer to itstructspaceshipchar*make;char*model;char*year;
        ship ="Incom Corporation","T-65 X-wing starfighter","128 ABY",*pship =&ship;printf("spaceship: %s %s %sn", ship.year, ship.make, ship.model);// addresses increase in order of definition// padding may be insertedstructAchar a;double b;char c;;printf("offset of char a = %zunoffset of double b = %zunoffset of char c = %zun""sizeof(struct A)=%zun",offsetof(structA, a),offsetof(structA, b),offsetof(structA, c),sizeof(structA));structBchar a;char b;double c;;printf("offset of char a = %zunoffset of char b = %zunoffset of double c = %zun""sizeof(struct B)=%zun",offsetof(structB, a),offsetof(structB, b),offsetof(structB, c),sizeof(structB));// A pointer to a struct can be cast to a pointer to its first member and vice versachar* pmake =(char*)&ship;
    pship =(structspaceship*)pmake;

Posible salida:

car:1923 Nash 48 Sports Touring Car
spaceship:128 ABY Incom Corporation T-65 X-wing starfighter
offset of char a =0
offset of double b =8
offset of char c =16sizeof(structA)=24
offset of char a =0
offset of char b =1
offset of double c =8sizeof(structB)=16

Referencias

  • Estándar C11 (ISO / IEC 9899: 2011):
    • 6.7.2.1 Especificadores de estructura y unión (p: 112-117)
  • Estándar C99 (ISO / IEC 9899: 1999):
    • 6.7.2.1 Especificadores de estructura y unión (p: 101-104)
  • Estándar C89 / C90 (ISO / IEC 9899: 1990):
    • 3.5.2.1 Especificadores de estructura y unión

Ver también

  • acceso a estructura y miembro de unión
  • campo de bits
  • inicialización de estructura