Pular para o conteúdo

Ponteiros

Aritmética por elemento, cast, distância — e as duas formas de um ponteiro não valer nada.

Andar por elemento, e não por byte#

dataforge
p := Est.ponteiro(numeros, "u32")

out p.ler()
out p.mais(1).ler()          // o PRÓXIMO u32
out p.mais(1).endereco()     // 4  e não 1
out p.cluster(4)             // os quatro a partir daqui

p + 1 num u32* do C anda quatro bytes. Andar um byte é um índice, não um ponteiro — e é a conta que quem escreve C faz o tempo todo. p.distancia(q) responde na mesma unidade, e é recusada entre tipos diferentes: a conta é em elementos, e dois tipos têm tamanhos diferentes.

O cast#

dataforge
p.como("u8").mais(3).ler()   // os mesmos bytes, outro tipo

As duas formas de não valer nada#

O que é
Est.nulo()o endereço existe e vale zero; lê-lo seria a falha de segmentação clássica
bloco liberadoo endereço continua na mão de alguém, e o bloco declarou o fim
dataforge
p := Est.nulo()
out p.e_nulo()      // yes
p.ler()             // NullPointerError

morto := Est.bloco(8)
q := Est.ponteiro(morto, "u32")
morto.liberar()
q.ler()             // DanglingPointerError

NullPointerError é diferente de NullReferenceError, que fala de um void da linguagem. Aqui o endereço existe.

O ponteiro segura o bloco — e isso é uma decisão#

União#

dataforge
Valor := Est.uniao("Valor", [
    ["inteiro", "u32"],
    ["flutuante", "f32"]
], ordem := "rede")

Valor.escrever(caixa, {"flutuante": 1.0})
out Valor.ler(caixa)["inteiro"]     // 1065353216  o IEEE 754 de 1.0

Todos os campos no mesmo deslocamento zero, e o tamanho é o do maior. Escrever um e ler outro devolve a reinterpretação dos bytes — que é o ponto de uma união, e também o que a torna perigosa quando o tipo escrito não é registrado em algum lugar.

O exemplo completo#

examples/estrutura_binaria.df monta um arquivo com cabeçalho e três registros, percorre com janelas, escreve por ponteiro e demonstra as cinco recusas — com assert em cada afirmação.