Compartir por


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