Então, basicamente, estou com dificuldade para entender o alinhamento de dados. Não entendo por que em uma arquitetura de 64 bits, por exemplo, é importante armazenar dados de 4 bytes em um múltiplo do endereço 0x0, 0x4, 0x8, 0xC. A busca da CPU começa em cada múltiplo do tamanho da palavra (que é 8 bytes aqui)? E por que dados de 2 bytes precisam ser armazenados nos endereços 0x0, 0x2, 0x4, 0x6, 0x8, 0xA, 0xC, 0xE? A CPU pode carregar em um clock dados de 2 bytes, mesmo se estiverem armazenados em 0x1... Então, por que eles deveriam estar no endereço 0x0, 0x2, 0x4, 0x6, 0x8, 0xA, 0xC, 0xE.
Além disso, se a linha de cache da CPU tiver, por exemplo, 64 bytes, por que devo me preocupar com o alinhamento de dados se os dados não se sobrepõem entre os endereços 0x...00 e 0x...40? É confuso...
Para um objeto de n bytes menor que o tamanho da palavra usada para acessar a memória, garantir que o objeto esteja alinhado a um múltiplo de n bytes garante que o objeto não ficará entre palavras (desde que n seja um fator do tamanho da palavra).
Suponha que uma máquina tenha uma interface de memória de oito bytes: Cada sequência alinhada de oito bytes pode ser lida da memória ou escrita na memória com uma única operação de transferência. Então, todos os oito bytes de 0 a 7 podem ser lidos da memória em uma transferência, todos os oito bytes de 8 a 15 podem ser lidos da memória em uma transferência, e assim por diante. Mas ler apenas os dois bytes 7 e 8 exigiria duas transferências, porque a arquitetura da máquina não pode ler apenas quaisquer oito bytes em uma transferência; ela pode ler apenas uma sequência de oito bytes começando em um múltiplo de oito.
Agora considere um tipo de objeto de quatro bytes, digamos
int
. Quando alguém declara um array desses,int a[7];
, o que acontece quandoa
começa no endereço 2? O objetoa[0]
está nos bytes 2, 3, 4 e 5. O objetoa[1]
está nos bytes 6, 7, 8 e 9. E assim por diante.a[0]
pode ser lido em uma única transferência de memória. A CPU pode obter os bytes 0-7 em uma transferência e retirara[0]
os bytes 2-5. No entanto,a[1]
não pode ser lido em uma única transferência de memória. A CPU não pode ler os bytes 6, 7, 8 e 9 em uma transferência. Ela precisa emitir uma transferência para obter os bytes 0-7 e outra para obter os bytes 8-9.Quando exigimos que um tipo de objeto de quatro bytes tenha alinhamento de quatro bytes, evitamos isso. Então, o array
a
deint a[7];
não poderia começar no byte 2. Ele teria que começar no byte 0, 4, 8, 12 e assim por diante. Se, por exemplo, ele começar no byte 4, entãoa[0]
está nos bytes 4-7, que estão dentro do conjunto de oito bytes 0-7.a[1]
está em 8-11, que está dentro de 8-15.a[2]
está em 12-15, que está dentro de 8-15. E assim, cada elemento dea
está dentro de um conjunto de oito bytes de bytes alinhados. Então, o acesso à memória será mais eficiente do que sea
não estivesse alinhado em quatro bytes.