Alinhamento (C11)
Um dos recursos de baixo nível do C é a capacidade de especificar o alinhamento preciso de objetos na memória para tirar o máximo proveito da arquitetura de hardware.
As CPUs leem e gravam memória com mais eficiência quando armazenam dados em um endereço que é um múltiplo do tamanho dos dados. Por exemplo, um inteiro de 4 bytes será acessado com mais eficiência se ele for armazenado em um endereço que seja um múltiplo de 4. Quando os dados não estão alinhados, a CPU trabalha mais para fazer os cálculos de endereço para acessar os dados.
Por padrão, o compilador alinha dados com base em seu tamanho: char
em um limite de 1 byte, short
em um limite de 2 bytes, int
, long
e float
em um limite de 4 bytes, double
no limite de 8 bytes e assim por diante.
Além disso, ao alinhar os dados usados com frequência com o tamanho da linha de cache do processador, você melhora o desempenho do cache. Por exemplo, digamos que você defina uma estrutura cujo tamanho seja menor que 32 bytes. Talvez você queira usar o alinhamento de 32 bytes para garantir que todas as instâncias da estrutura sejam armazenadas em cache com eficiência.
Normalmente, não é necessário se preocupar com alinhamento. O compilador geralmente alinha dados em limites naturais baseados no processador de destino e no tamanho dos dados. Os dados são alinhados em limites de até 4 bytes em processadores de 32 bits e limites de 8 bytes em processadores de 64 bits. Em alguns casos, no entanto, você pode obter melhorias de desempenho ou economia de memória, especificando um alinhamento personalizado para suas estruturas de dados.
Use a palavra-chave _Alignof
C11 para obter o alinhamento preferencial de um tipo ou variável e _Alignas
para especificar um alinhamento personalizado para um tipo definido pelo usuário ou variável.
As macros de conveniência alignof
e alignas
, definidas em <stdalign.h>
, mapeiam diretamente para _Alignof
e _Alignas
, respectivamente. Essas macros correspondem às palavras-chave usadas no C++. Portanto, usar as macros em vez das palavras-chave C pode ser útil para portabilidade de código se você compartilhar qualquer código entre os dois idiomas.
alignas
e _Alignas
(C11)
Use alignas
ou _Alignas
para especificar o alinhamento personalizado para um tipo definido pelo usuário ou variável. Eles podem ser aplicados a um struct, união, enumeração ou variável.
Sintaxe de alignas
alignas(type)
alignas(constant-expression)
_Alignas(type)
_Alignas(constant-expression)
Comentários
_Alignas
não pode ser usado na declaração de um typedef, campo de bit, função, parâmetro de função ou um objeto declarado com o especificador register
.
Especifique um alinhamento que seja uma potência de dois, como 1, 2, 4, 8, 16 e assim por diante. Não use um valor menor que o tamanho do tipo.
Os tipos struct
e union
têm um alinhamento igual ao maior alinhamento de qualquer membro. Bytes de preenchimento são adicionados dentro de um struct
para garantir que os requisitos de alinhamento de membros individuais sejam atendidos.
Se houver vários especificadores alignas
em uma declaração (por exemplo, um struct
com vários membros que têm especificadores alignas
diferentes), o alinhamento do struct
será pelo menos o valor do maior especificador.
Exemplo do alignas
Este exemplo usa a macro alignof
de conveniência porque ela é portátil para C++. O comportamento será o mesmo se você usar _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
e _Alignof
(C11)
_Alignof
e seu alias alignof
retornam o alinhamento em bytes do tipo especificado. Retornam um valor de tipo size_t
.
Sintaxe de alignof
alignof(type)
_Alignof(type)
Exemplo do alignof
Este exemplo usa a macro alignof
de conveniência porque ela é portátil para C++. O comportamento será o mesmo se você usar _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
Compilar com /std:c11
.
O SDK do Windows 10.0.20348.0 (versão 2104) ou posterior. Consulte o SDK do Windows para baixar o SDK mais recente. Para obter instruções sobre como instalar e usar o SDK para desenvolvimento C11 e C17, consulte Instalar o suporte C11 e C17 no Visual Studio.
Confira também
/std
(Especificar a versão padrão da linguagem)
C++ alignof
e alignas
Tratamento do compilador de alinhamento de dados