Alineación (C11)
Una de las características de bajo nivel de C es la capacidad para especificar la alineación precisa de los objetos en la memoria con el fin de sacar el máximo partido a la arquitectura de hardware.
Las CPU leen y escriben en la memoria con más eficacia cuando almacenan datos en una dirección que es un múltiplo del tamaño de los datos. Por ejemplo, a un entero de 4 bytes se accede de una forma más eficiente si se almacena en una dirección que sea un múltiplo de 4. Cuando los datos no están alineados, la CPU trabaja más en el cálculo de la dirección para acceder a ellos.
De forma predeterminada, el compilador alinea los datos en función de su tamaño: char
en un límite de 1 byte, short
en un límite de 2 bytes, int
, long
y float
en un límite de 4 bytes, double
en un límite de 8 bytes, etc.
Además, al alinear los datos que más se usan con el tamaño de la línea de caché del procesador, se puede mejorar el rendimiento de la memoria caché. Por ejemplo, supongamos que define una estructura cuyo tamaño es inferior a 32 bytes. Es posible que desee usar la alineación de 32 bytes para asegurarse de que todas las instancias de la estructura se almacenan en caché de forma eficaz.
Normalmente, no es necesario preocuparse por la alineación. El compilador suele alinear los datos en los límites naturales en función del procesador de destino y el tamaño de los datos. Los datos se alinean en límites de hasta 4 bytes en los procesadores de 32 bits, y en límites de 8 bytes en procesadores de 64 bits. No obstante, en algunos casos se puede conseguir una mejora del rendimiento o un ahorro de memoria especificando una alineación personalizada para sus estructuras de datos.
Use la palabra clave de C11 _Alignof
para obtener la alineación preferida de un tipo o una variable, y _Alignas
para especificar una alineación personalizada para una variable o un tipo definido por el usuario.
Las macros de conveniencia alignof
y alignas
, definidas en <stdalign.h>
, se asignan directamente a _Alignof
y _Alignas
, respectivamente. Estas macros se corresponden con las palabras clave usadas en C++. Por tanto, el uso de estas macros en lugar de las palabras clave de C puede ser útil para la portabilidad del código si comparte algún código entre los dos lenguajes.
alignas
y _Alignas
(C11)
Use alignas
o _Alignas
para especificar la alineación personalizada para una variable o un tipo definido por el usuario. Se pueden aplicar a una estructura, una unión, una enumeración o una variable.
Sintaxis de alignas
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
Observaciones
_Alignas
no se puede usar en la declaración de una definición de tipo, un campo de bits, una función, un parámetro de una función ni un objeto declarado con el especificador register
.
Especifique una alineación que sea una potencia de dos, como 1, 2, 4, 8, 16, etc. No use un valor menor que el tamaño del tipo.
Los tipos struct
y union
tienen una alineación igual a la alineación más grande de cualquier miembro. Se agregan bytes de relleno dentro de una struct
para garantizar el cumplimiento de los requisitos de alineación de miembros individuales.
Si hay varios especificadores alignas
en una declaración (por ejemplo, una instancia de struct
con varios miembros que tienen especificadores alignas
diferentes), la alineación de struct
será al menos el valor del especificador más grande.
Ejemplo de alignas
En este ejemplo se usa la macro de conveniencia alignof
porque se puede portar a C++. El comportamiento es el mismo si usa _Alignof
.
// Compile with /std:c11
#include <stdio.h>
#include <stdalign.h>
typedef struct
{
int value; // aligns on a 4-byte boundary. There will be 28 bytes of padding between value and alignas
alignas(32) char alignedMemory[32]; // assuming a 32 byte friendly cache alignment
} cacheFriendly; // this struct will be 32-byte aligned because alignedMemory is 32-byte aligned and is the largest alignment specified in the struct
int main()
{
printf("sizeof(cacheFriendly): %d\n", sizeof(cacheFriendly)); // 4 bytes for int value + 32 bytes for alignedMemory[] + padding to ensure alignment
printf("alignof(cacheFriendly): %d\n", alignof(cacheFriendly)); // 32 because alignedMemory[] is aligned on a 32-byte boundary
/* output
sizeof(cacheFriendly): 64
alignof(cacheFriendly): 32
*/
}
alignof
y _Alignof
(C11)
_Alignof
y su alias alignof
devuelven la alineación en bytes del tipo especificado. Devuelve un valor de tipo size_t
.
Sintaxis de alignof
alignof(type)
_Alignof(type)
Ejemplo de alignof
En este ejemplo se usa la macro de conveniencia alignof
porque se puede portar a C++. El comportamiento es el mismo si usa _Alignof
.
// Compile with /std:c11
#include <stdalign.h>
#include <stdio.h>
int main()
{
size_t alignment = alignof(short);
printf("alignof(short) = %d\n", alignment); // 2
printf("alignof(int) = %d\n", alignof(int)); // 4
printf("alignof(long) = %d\n", alignof(long)); // 4
printf("alignof(float) = %d\n", alignof(float)); // 4
printf("alignof(double) = %d\n", alignof(double)); // 8
typedef struct
{
int a;
double b;
} test;
printf("alignof(test) = %d\n", alignof(test)); // 8 because that is the alignment of the largest element in the structure
/* output
alignof(short) = 2
alignof(int) = 4
alignof(long) = 4
alignof(float) = 4
alignof(double) = 8
alignof(test) = 8
*/
}
Requisitos
Compile con /std:c11
.
Windows SDK 10.0.20348.0 (versión 2104) o posterior. Consulte Windows SDK para descargar el SDK más reciente. Para obtener instrucciones sobre cómo instalar y usar el SDK para el desarrollo con C11 y C17, vea Instalación de la compatibilidad con C11 y C17 en Visual Studio.
Vea también
/std
(Especificar la versión estándar del lenguaje)
alignof
y alignas
de C++
Control del compilador de la alineación de datos