Pregunta

Escuché el rumor de que, en C, las matrices que están contenidas dentro de estructuras pueden tener relleno agregado entre los elementos de la matriz.Ahora bien, obviamente, la cantidad de relleno no puede variar entre ningún par de elementos o calcular el siguiente elemento en una matriz no es posible con aritmética de puntero simple.

Este rumor también afirmaba que se garantiza que las matrices que no están contenidas en estructuras no contienen relleno.Sé que al menos esa parte es cierta.

Entonces, en código, el rumor es:

{
    // Given this:
    struct { int values[20]; } foo;
    int values[20];

    // This may be true:
    sizeof(values) != sizeof(foo.values);
}

Estoy bastante seguro de que sizeof(values) siempre será igual sizeof(foo.values).Sin embargo, no he podido encontrar nada en el estándar C (específicamente C99) que confirme o niegue esto explícitamente.

¿Alguien sabe si este rumor se aborda en algún estándar C?

editar:Entiendo que puede haber relleno entre el final de la matriz foo.values y el final de la estructura foo y que el estándar establece que no habrá relleno entre el inicio de foo y el comienzo de foo.values.Sin embargo, ¿alguien tiene una cita de o referencia a el estándar donde dice que no hay relleno entre los elementos de foo.values?

¿Fue útil?

Solución

No, nunca habrá relleno en entre elementos de una matriz. Específicamente que no está permitido. El estándar C99 llama tipos de matriz "un tipo de matriz describe un conjunto no vacío de forma contigua asignado de objetos ...". Por el contrario, una estructura es "secuencialmente", no "contigua" asignado.

Puede haber relleno antes o después de una matriz dentro de una estructura; que es otro animal completo. El compilador puede hacer eso a ayuda a la alineación de la estructura, pero el nivel C no decir nada sobre eso.

Otros consejos

Cuidado aquí.Se puede agregar relleno al final de la estructura, pero no se agregará entre los elementos de la matriz como usted indica en su pregunta.Las matrices siempre harán referencia a la memoria contigua, aunque a una matriz de estructuras se le puede agregar relleno a cada elemento como parte de la propia estructura.

En su ejemplo, el values y foo.values Las matrices tendrán el mismo tamaño.Cualquier relleno será parte de la estructura. foo en cambio.

Aquí está la explicación de por ¿Por qué una estructura puede necesitar relleno entre sus miembros o incluso después de su último miembro, y por qué una matriz no:

Los diferentes tipos pueden tener diferentes requisitos de alineación. Algunos tipos deben estar alineados en límites de palabra, otros en los límites dobles o incluso cuádruples palabra. Para lograr esto, una estructura puede contener bytes de relleno entre sus miembros. Arrastran bytes de relleno pueden ser necesarios debido a que la posición de memoria directamente ofter una estructura debe también conforme con los requisitos de alineación de la estructura, es decir, si bar es de tipo struct foo *, entonces

(struct foo *)((char *)bar + sizeof(struct foo))

produce un puntero válido a struct foo (es decir, no fallan debido a la falta de alineación).

A medida que cada 'miembro' de una matriz tiene el mismo requisito de alineación, no hay razón para introducir el relleno. Esto es cierto para las matrices contenidas en estructuras, así:. Si primero Elment de una matriz está alineado correctamente, por lo que son todos los elementos siguientes

Sí, algo así. Las variables se suelen destinarse a algún sitio limítrofe, en función de la variable. Tome la siguiente, por ejemplo:

typedef struct
{
    double d;
    char c;
} a_type_t;

doble y carbón son 8 y 1 bytes, en mi sistema, respectivamente. Total de 9. Esa estructura, sin embargo, será de 16 bytes, por lo que el partido de dobles siempre estarán alineados de 8 bytes. Si tuviera sólo enteros usados, caracteres, etc, a continuación, la alineación puede ser 1, 2, 4, u 8.

Para obtener algún tipo T, sizeof(T) puede o puede no ser igual sizeof(T.a) + sizeof(T.b) + sizeof(T.c) ... etc.

Generalmente, esto es totalmente compilador y dependiente de la arquitectura. En la práctica, nunca importa.

Considere lo siguiente:

struct {
  short s;
  int i;
} s;

Suponiendo cortos son de 16 bits y estás en 32 bits, el tamaño será probablemente ser de 8 bytes cada uno como miembros de la estructura tiende a alinearse una palabra (32 bits en este caso) de frontera. Digo "probablemente" porque es un comportamiento específico de la implementación que se pueden variarse parámetros del compilador y similares.

Vale la pena subrayar que este es un comportamiento aplicación no necesariamente definido por la norma C. Al igual que el tamaño de los pantalones cortos, largos y enteros (el estándar de C simplemente dice pantalones cortos no serán más grandes que anhela enteros y no serán más pequeños que enteros, que puede terminar como 16/32/32, 16/32/64 , 32/32/64 o un número de otras configuraciones).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top