0Pricing
Swift Academy · Aula

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)    // 8

size — 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 // 160

alignment — 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)  // 8

A 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) // 16

Deslocamentos 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) // 8

Reordenando 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 reference

Opcionais 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 byte

Usando 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)) // 8

Alocando 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

  1. MemoryLayout e Alinhamento
  2. UnsafePointer e UnsafeMutablePointer
  3. Ponteiros de Buffer Inseguros
  4. withUnsafeBytes e Interoperabilidade com C
← Voltar para Swift Academy