[Lenguaje C] ¿Qué es la alineación de la memoria estructural? ¿Cómo calcular el tamaño de la estructura?

 

Tabla de contenido

1. Alineación de la memoria de la estructura

Comprensión de la compensación:​

2. Cálculo del tamaño de la estructura.

2.1 En la estructura, solo el cálculo del tamaño de los tipos de datos comunes

2.2 Cálculo del tamaño de la estructura anidada en la estructura.

3. Modificar el número de alineación predeterminado.

4. ¿Por qué existe la alineación de la memoria?


Este artículo presenta principalmente la alineación de la memoria de la estructura y cómo calcular el tamaño.

Antes de aprender la alineación de la memoria de estructuras, no sé si te habrás dado cuenta de que cuando tenemos dos estructuras con el mismo tipo y número de variables miembro, pero el orden es diferente, al calcular su tamaño, sus tamaños son diferentes, como por ejemplo el siguiente código:

#include<stdio.h>
struct S1
{
	char c1;
	int i;
	char c2;
};
struct S2
{
	int i;
	char c1;
	char c2;
};
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	return 0;
}

Los tamaños calculados por sizeof no son los mismos:

 Ahora, aprendamos a calcular el tamaño de la estructura.

1. Alineación de la memoria de la estructura

Alineación de memoria estructural significa que cuando el compilador asigna el espacio de memoria de la variable de estructura, organiza los miembros de la estructura de acuerdo con ciertas reglas para garantizar la eficiencia del acceso de la estructura y los requisitos de alineación de la memoria.

Antes de calcular el tamaño de la estructura, debemos comprender las reglas de alineación de la memoria de la estructura :

1. El primer miembro está en la dirección cuyo desplazamiento es 0 de la variable de estructura.

2. Otras variables miembro deben alinearse con una dirección que sea un múltiplo entero de un determinado número (número de alineación). Alineación = alineación predeterminada del compilador y el valor más pequeño del tamaño del miembro . El valor predeterminado en VS es 8 , no hay un número de alineación predeterminado en Linux y el número de alineación es el tamaño del miembro mismo.

3. El tamaño total de la estructura es un múltiplo entero del número de alineación máximo (cada variable miembro tiene un número de alineación).

4. Si una estructura está anidada, la estructura anidada se alinea con un múltiplo entero de su propia alineación máxima, y ​​el tamaño total de la estructura es el número entero de todas las alineaciones máximas (incluida la alineación de la estructura anidada) veces.


Comprensión de la compensación:

 Utilice offsetof para calcular el desplazamiento de la variable miembro de la estructura en comparación con la posición inicial de la estructura.

#include<stddef.h>
#include<stdio.h>
struct S1
{
	char c1;
	int i;
	char c2;
};
int main()
{
	printf("%d\n", offsetof(struct S1, c1));
	printf("%d\n", offsetof(struct S1, i));
	printf("%d\n", offsetof(struct S1, c2));
	return 0;
}

Según el desplazamiento de cada variable miembro, podemos calcular la ubicación de almacenamiento de la variable miembro de estructura en la memoria:

Según el análisis de los fenómenos anteriores, encontramos que los miembros de la estructura no se almacenan continuamente en la memoria .

Si queremos saber por qué hay espacio desperdiciado, tenemos que seguir aprendiendo según las reglas de alineación de la estructura.

 

2. Cálculo del tamaño de la estructura.

A continuación se explica cómo calcular el tamaño de la estructura de acuerdo con las reglas de alineación de memoria de la estructura:

2.1 En la estructura, solo el cálculo del tamaño de los tipos de datos comunes

O tome este tipo de estructura como ejemplo:

struct S1
{
	char c1;
	int i;
	char c2;
};

 

De la misma forma, calcule el tamaño de la siguiente estructura:

struct S2
{
	int i;
	char c1;
	char c2;
};

 Llegados a este punto, la cuestión inicial ha quedado resuelta.

Para consolidar los conocimientos aprendidos, aquí tienes otro ejemplo de cálculo del tamaño de una estructura:

struct S3
{
	double d;
	char c;
	int i;
};

 

¿Cómo calcular el tamaño cuando la estructura contiene una matriz?

Cuando hay variables de tipo matriz en la estructura, solo necesitamos considerar la matriz como múltiples variables del mismo tipo, como se muestra en la siguiente figura:

 Compile la prueba:

2.2 Cálculo del tamaño de la estructura anidada en la estructura.

Para estructuras con estructuras anidadas, debemos utilizar la cuarta regla:

Si una estructura está anidada, la estructura anidada se alinea con un múltiplo entero de su propia alineación máxima, y ​​el tamaño total de la estructura es un múltiplo entero de todas las alineaciones máximas (incluida la alineación de la estructura anidada).

Calcular un intento:

struct S
{
	double d1;
	char c1;
	int i;
};
struct S7
{
	char c2;
	struct S s;
	double d2;
};
int main()
{
	printf("%d\n", sizeof(struct S7));
	return 0;
}

 

3. Modificar el número de alineación predeterminado.

Hemos visto la directiva de preprocesamiento #pragma antes y aquí la usamos nuevamente para cambiar nuestra alineación predeterminada.

#pragma pack(8)//设置默认对齐数为8
struct S1
{
	char c1;
	int i;
	char c2;
};
#pragma pack() //取消设置的默认对齐数,还原为默认

#pragma pack(1)//设置默认对齐数为1
struct S2
{
	char c1;
	int i;
	char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认

int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	return 0;
}

Resultado de salida: 

En circunstancias normales, el número de alineación se establece en una potencia de 2 y no se establecerá en otros números a voluntad.

 Conclusión: Cuando la alineación de la estructura no es adecuada, podemos cambiar la alineación predeterminada nosotros mismos.



4. ¿Por qué existe la alineación de la memoria?

La mayoría de las referencias dicen algo como esto:

1. Motivo de la plataforma (motivo del trasplante):

No todas las plataformas de hardware pueden acceder a datos arbitrarios en cualquier dirección; algunas plataformas de hardware solo pueden recuperar ciertos tipos de datos en ciertas direcciones; de lo contrario, se genera una excepción de hardware.

2. Razones de rendimiento:

Las estructuras de datos (especialmente las pilas) deben estar alineadas dentro de límites naturales tanto como sea posible. La razón es que para acceder a la memoria no alineada, el procesador necesita realizar dos accesos a la memoria; mientras que los accesos a la memoria alineada requieren solo un acceso.

En general: el alineamiento memorístico de la estructura es la práctica de intercambiar espacio por tiempo.

expandir: 

        Alineación de memoria estructural significa que cuando el compilador asigna el espacio de memoria de la variable de estructura, organiza los miembros de la estructura de acuerdo con ciertas reglas para garantizar la eficiencia del acceso de la estructura y los requisitos de alineación de la memoria.

En una computadora, la velocidad a la que se puede acceder a la memoria está limitada y generalmente por un tamaño de byte específico. Para mejorar la eficiencia del acceso a la memoria, muchas arquitecturas informáticas requieren que la dirección de ciertos tipos de datos en la memoria sea un múltiplo de un determinado valor. Este valor específico suele ser el tamaño del tipo de datos o el tamaño de palabra del procesador.

El propósito de la alineación de la memoria estructural es cumplir con estos requisitos de alineación para reducir el tiempo y el costo del acceso a la memoria. Cuando las variables miembro de la estructura se organizan de acuerdo con las reglas de alineación, se puede garantizar que la dirección de cada variable miembro esté alineada, mejorando así la eficiencia del acceso a la memoria.

        Las reglas de alineación exactas pueden variar según el compilador, el sistema operativo y el procesador. En general, las reglas de alineación tienen en cuenta el tamaño y los requisitos de alineación de los tipos de datos, y el orden y los tipos de los miembros de la estructura. El compilador insertará bytes de relleno (Padding Bytes) entre los miembros de la estructura para garantizar que la dirección de cada miembro cumpla con los requisitos de alineación.

Cabe señalar que la alineación de la memoria de la estructura puede hacer que el tamaño de la estructura aumente, porque los bytes de relleno ocuparán espacio de memoria adicional. Este aumento de tamaño puede afectar el diseño de la memoria y la huella de memoria de las estructuras, especialmente cuando se trata de anidamiento de estructuras, matrices y E/S de archivos.

        En algunos casos especiales, puede utilizar las instrucciones o atributos proporcionados por el compilador para controlar la alineación de la memoria de la estructura para satisfacer necesidades específicas.

Al diseñar la estructura debemos satisfacer la alineación y ahorrar espacio.Cómo hacerlo:

Deje que los miembros que ocupan un espacio pequeño se reúnan tanto como sea posible.

struct S1
{
 char c1;
 int i;
 char c2;
};
struct S2
{
 char c1;
 char c2;
 int i;
};

Los miembros de los tipos S1 y S2 son exactamente iguales, pero existen algunas diferencias en el tamaño del espacio ocupado por S1 y S2.

Supongo que te gusta

Origin blog.csdn.net/m0_73648729/article/details/132391741
Recomendado
Clasificación