@sizeOf em Zig
O @sizeOf retorna o tamanho de armazenamento de um tipo em bytes, incluindo qualquer padding de alinhamento. É o equivalente do sizeof do C, mas disponível como builtin em tempo de compilação. Fundamental para alocação de memória, serialização e interoperabilidade com código C.
Sintaxe
@sizeOf(comptime T: type) comptime_int
O que faz
O @sizeOf consulta o tamanho que um valor do tipo especificado ocupa na memória, em bytes. O valor retornado inclui qualquer padding inserido pelo compilador para manter o alinhamento correto. Este é o número de bytes que um std.mem.Allocator alocaria para uma instância desse tipo.
Parâmetros
- T (
type, comptime): O tipo cujo tamanho será consultado. Pode ser qualquer tipo válido excetocomptime_int,comptime_floate outros tipos que existem apenas em comptime.
Valor de retorno
Retorna um comptime_int representando o tamanho em bytes do tipo.
Exemplos práticos
Exemplo 1: Tamanho de tipos primitivos
const std = @import("std");
test "tamanho de tipos primitivos" {
try std.testing.expect(@sizeOf(u8) == 1);
try std.testing.expect(@sizeOf(u16) == 2);
try std.testing.expect(@sizeOf(u32) == 4);
try std.testing.expect(@sizeOf(u64) == 8);
try std.testing.expect(@sizeOf(i32) == 4);
try std.testing.expect(@sizeOf(f32) == 4);
try std.testing.expect(@sizeOf(f64) == 8);
try std.testing.expect(@sizeOf(bool) == 1);
// Ponteiros em sistemas de 64 bits
try std.testing.expect(@sizeOf(*u8) == 8);
try std.testing.expect(@sizeOf(usize) == 8);
}
Exemplo 2: Entendendo padding em structs
const std = @import("std");
const SemPadding = struct {
a: u32,
b: u32,
};
const ComPadding = struct {
a: u8, // 1 byte + 7 de padding
b: u64, // 8 bytes
c: u8, // 1 byte + 7 de padding
};
const Otimizada = struct {
b: u64, // 8 bytes
a: u8, // 1 byte
c: u8, // 1 byte + 6 de padding
};
test "padding em structs" {
try std.testing.expect(@sizeOf(SemPadding) == 8); // 4 + 4
std.debug.print("ComPadding: {} bytes\n", .{@sizeOf(ComPadding)});
std.debug.print("Otimizada: {} bytes\n", .{@sizeOf(Otimizada)});
// Reordenar campos pode reduzir o tamanho total
// ComPadding provavelmente é 24 bytes (com padding)
// Otimizada provavelmente é 16 bytes (menos padding)
}
Exemplo 3: Buffer de serialização
const std = @import("std");
const Cabecalho = packed struct {
versao: u8,
tipo: u8,
tamanho: u16,
id: u32,
};
fn serializar(cabecalho: Cabecalho) [@sizeOf(Cabecalho)]u8 {
return @bitCast(cabecalho);
}
fn deserializar(bytes: [@sizeOf(Cabecalho)]u8) Cabecalho {
return @bitCast(bytes);
}
test "serialização com tamanho conhecido" {
// packed struct garante layout previsível
try std.testing.expect(@sizeOf(Cabecalho) == 8);
const cab = Cabecalho{
.versao = 1,
.tipo = 3,
.tamanho = 256,
.id = 42,
};
const bytes = serializar(cab);
const recuperado = deserializar(bytes);
try std.testing.expect(recuperado.versao == 1);
try std.testing.expect(recuperado.id == 42);
}
Casos de uso comuns
- Alocação de memória: Calcular quantos bytes alocar para arrays ou buffers de tipos específicos.
- Serialização binária: Determinar o tamanho de estruturas para leitura/escrita em arquivos ou rede.
- Interoperabilidade com C: Garantir que structs Zig tenham o mesmo tamanho que as equivalentes em C.
- Otimização de structs: Comparar tamanhos com diferentes ordenações de campos para minimizar padding.
- Pools de memória: Dimensionar pools e caches baseados no tamanho dos objetos armazenados.
Diferenças entre @sizeOf e @bitSizeOf
@sizeOfretorna o tamanho em bytes, incluindo padding de alinhamento.@bitSizeOfretorna o tamanho em bits, sem incluir padding extra.- Para um
u24,@sizeOfretorna 4 (arredondado para bytes com alinhamento), enquanto@bitSizeOfretorna 24.
Builtins relacionados
- @bitSizeOf — Retorna o tamanho em bits
- @alignOf — Retorna o alinhamento de um tipo
- @typeInfo — Informações detalhadas sobre o tipo
- @memcpy — Copia bloco de memória