MemoryLayout e Alinhamento
Inspecione o tamanho, o passo e o alinhamento dos tipos.
MemoryLayout e Alinhamento é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.
Por que o layout da memória é importante
Ao trabalhar com Swift inseguro ou fazer a ponte com C, você precisa saber como os valores são organizados na memória. O Swift oferece MemoryLayout<T> para inspecionar isso sem jamais tocar em raw bytes.
Ele responde a três perguntas: qual é o tamanho de um valor, qual é a distância entre os valores em um vetor e em qual limite de endereço um valor deve começar.
// MemoryLayout works on any type
print(MemoryLayout<Int>.size) // 8 on 64-bit
print(MemoryLayout<Bool>.size) // 1
print(MemoryLayout<Double>.size) // 8size — Armazenamento real
MemoryLayout<T>.size é a quantidade de bytes que os dados significativos do valor ocupam. Ele não inclui o preenchimento final que pode ficar entre os elementos de um vetor.
Use size quando quiser saber quantos bytes significativos um único valor contém.
struct Point {
var x: Int8 // 1 byte
var y: Int64 // 8 bytes
}
print(MemoryLayout<Point>.size) // 16 (not 9 — padding!)stride — Espaçamento em vetores
stride é a distância em bytes entre o início de um elemento e o seguinte quando os valores são armazenados em um vetor contíguo. Ela equivale a size arredondado para cima até o valor de alignment.
Ao alocar buffers manualmente, multiplique por stride, nunca por size.
print(MemoryLayout<Point>.stride) // 16
print(MemoryLayout<Int8>.stride) // 1
// Buffer for 10 Points needs:
let bytes = 10 * MemoryLayout<Point>.stride // 160alignment — Limites de endereço
alignment é o limite de bytes no qual um valor deve começar. Um Int64 com alignment 8 deve começar em um endereço divisível por 8. O compilador insere preenchimento para respeitar isso.
O alignment de uma estrutura é o maior alignment entre seus membros.
print(MemoryLayout<Int8>.alignment) // 1
print(MemoryLayout<Int64>.alignment) // 8
print(MemoryLayout<Point>.alignment) // 8A diferença entre size e stride
Para muitos tipos, size == stride, mas eles divergem sempre que existe preenchimento. Uma estrutura pode ter size 9 e ainda assim stride 16, porque o elemento seguinte precisa estar alinhado a 8 bytes.
Regra prática: analise um valor individual com size e coleções com stride.
struct Mixed {
var flag: Bool // 1
var value: Int // 8
}
print(MemoryLayout<Mixed>.size) // 16
print(MemoryLayout<Mixed>.stride) // 16Deslocamentos dos campos
Para estruturas, você pode consultar onde cada propriedade armazenada fica em relação ao início usando MemoryLayout<T>.offset(of:) com um caminho de chave. Isso é essencial ao organizar dados para corresponder a uma estrutura de C.
struct Header {
var magic: UInt32 // offset 0
var length: UInt64 // offset 8 (padded)
}
print(MemoryLayout<Header>.offset(of: \Header.magic) ?? -1) // 0
print(MemoryLayout<Header>.offset(of: \Header.length) ?? -1) // 8Reordenando para economizar espaço
Por causa do alinhamento, a ordem das propriedades armazenadas afeta o tamanho. Colocar campos maiores primeiro ou agrupá-los por tamanho pode reduzir uma estrutura. Isso é importante para vetores grandes, nos quais bytes desperdiçados se acumulam.
struct Wasteful { var a: Int8; var b: Int64; var c: Int8 } // size 24
struct Tight { var b: Int64; var a: Int8; var c: Int8 } // size 16
print(MemoryLayout<Wasteful>.size)
print(MemoryLayout<Tight>.size)Layout das referências
Uma instância de uma classe é alocada no heap, portanto uma variável que contém uma referência de classe é apenas um ponteiro. Seu MemoryLayout.size é o tamanho do ponteiro (8 bytes), independentemente do tamanho do objeto.
Tipos de valor, como estruturas, armazenam seu conteúdo diretamente; tipos de referência armazenam apenas o ponteiro.
class Big { var data = [Int](repeating: 0, count: 1000) }
print(MemoryLayout<Big>.size) // 8 — just the referenceOpcionais e enumerações
Os opcionais geralmente adicionam um byte para a marcação, mas o Swift otimiza os opcionais de referência reutilizando o ponteiro nulo, portanto String? pode ter o mesmo tamanho que String.
Enumerações com valores associados têm tamanho suficiente para armazenar seu maior caso, além de um discriminador.
print(MemoryLayout<Int?>.size) // 9
print(MemoryLayout<String>.size) // 16
print(MemoryLayout<String?>.size) // 16 — no extra byteUsando a forma baseada em instância
Cada membro (size, stride, alignment) também tem uma forma baseada em instância: MemoryLayout.size(ofValue:). Isso é útil quando é difícil escrever o tipo explicitamente ou quando ele é inferido.
let tuple = (UInt8(1), UInt64(2))
print(MemoryLayout.size(ofValue: tuple)) // 16
print(MemoryLayout.stride(ofValue: tuple)) // 16
print(MemoryLayout.alignment(ofValue: tuple)) // 8Alocando com o layout correto
Ao alocar memória raw, você deve informar tanto a contagem de bytes quanto alignment. Obter esses valores de MemoryLayout garante a correção em diferentes arquiteturas, em vez de fixar números.
let count = 4
let capacity = count * MemoryLayout<Int>.stride
let align = MemoryLayout<Int>.alignment
let raw = UnsafeMutableRawPointer.allocate(
byteCount: capacity, alignment: align)
defer { raw.deallocate() }Verificação rápida
Teste sua compreensão da diferença entre size e stride.
Recapitulação
Você aprendeu os três pilares do layout da memória:
- size — bytes significativos de um único valor
- stride — espaçamento entre elementos de um vetor (use-o para alocação)
- alignment — limite inicial obrigatório
Você também viu offset(of:) para as posições dos campos, como a ordem das propriedades afeta o tamanho e que as referências têm apenas o tamanho de um ponteiro. Essas ferramentas permitem alocar e interpretar memória raw com segurança.
Perguntas Frequentes
A aula “MemoryLayout e Alinhamento” é grátis?
Sim — o texto completo de “MemoryLayout e Alinhamento” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.
O que vou aprender em “MemoryLayout e Alinhamento”?
Inspecione o tamanho, o passo e o alinhamento dos tipos. Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Swift Academy?
Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “MemoryLayout e Alinhamento”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Swift Academy?
Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- MemoryLayout e Alinhamento
- UnsafePointer e UnsafeMutablePointer
- Ponteiros de Buffer Inseguros
- withUnsafeBytes e Interoperabilidade com C