Skip to main content
Version: Zig 0.13.0

Formatting specifiers

std.fmt provides options for formatting various data types.

From here on, we'll be using std.testing.expectEqualStrings. This prints out information if our strings aren't equal, and better conveys our intent over using std.testing.expect and std.mem.eql. It's worth noting that the "strings" we're operating on are just []const u8 values where we trust that the buffer is valid UTF-8.

std.fmt.fmtSliceHexLower and std.fmt.fmtSliceHexUpper provide hex formatting for strings as well as {x} and {X} for ints.

const std = @import("std");
const eql = std.mem.eql;
const expect = std.testing.expect;

const bufPrint = std.fmt.bufPrint;
const expectEqualStrings = std.testing.expectEqualStrings;

test "hex" {
var b: [10]u8 = undefined;

try expectEqualStrings(
"FFFFFFFE",
try bufPrint(&b, "{X}", .{4294967294}),
);

try expectEqualStrings(
"fffffffe",
try bufPrint(&b, "{x}", .{4294967294}),
);

try expectEqualStrings(
"0xAAAAAAAA",
try bufPrint(&b, "0x{X}", .{2863311530}),
);

try expectEqualStrings(
"5a696721",
try bufPrint(&b, "{}", .{
std.fmt.fmtSliceHexLower("Zig!"),
}),
);
}

{d} performs decimal formatting for numeric types.

const std = @import("std");
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
test "decimal float" {
var b: [4]u8 = undefined;
try expectEqualStrings(
"16.5",
try bufPrint(&b, "{d}", .{16.5}),
);
}

{c} formats a byte into an ascii character.

const std = @import("std");
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
test "ascii fmt" {
var b: [1]u8 = undefined;
try expectEqualStrings(
"B",
try bufPrint(&b, "{c}", .{66}),
);
}

std.fmt.fmtIntSizeDec and std.fmt.fmtIntSizeBin output memory sizes in metric (1000) and power-of-two (1024) based notation.

const std = @import("std");
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
const fmtIntSizeDec = std.fmt.fmtIntSizeDec;
const fmtIntSizeBin = std.fmt.fmtIntSizeBin;

test "B Bi" {
var b: [32]u8 = undefined;

try expectEqualStrings("1B", try bufPrint(&b, "{}", .{fmtIntSizeDec(1)}));
try expectEqualStrings("1B", try bufPrint(&b, "{}", .{fmtIntSizeBin(1)}));

try expectEqualStrings("1.024kB", try bufPrint(&b, "{}", .{fmtIntSizeDec(1024)}));
try expectEqualStrings("1KiB", try bufPrint(&b, "{}", .{fmtIntSizeBin(1024)}));

try expectEqualStrings(
"1.073741824GB",
try bufPrint(&b, "{}", .{fmtIntSizeDec(1024 * 1024 * 1024)}),
);
try expectEqualStrings(
"1GiB",
try bufPrint(&b, "{}", .{fmtIntSizeBin(1024 * 1024 * 1024)}),
);
}

{b} and {o} output integers in binary and octal format.

const std = @import("std");
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
test "binary, octal fmt" {
var b: [8]u8 = undefined;

try expectEqualStrings(
"11111110",
try bufPrint(&b, "{b}", .{254}),
);

try expectEqualStrings(
"376",
try bufPrint(&b, "{o}", .{254}),
);
}

{*} performs pointer formatting, printing the address rather than the value.

const std = @import("std");
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
test "pointer fmt" {
var b: [16]u8 = undefined;
try expectEqualStrings(
"u8@deadbeef",
try bufPrint(&b, "{*}", .{@as(*u8, @ptrFromInt(0xDEADBEEF))}),
);
}

{e} outputs floats in scientific notation.

const std = @import("std");
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
test "scientific" {
var b: [16]u8 = undefined;

try expectEqualStrings(
try bufPrint(&b, "{e}", .{3.14159}),
"3.14159e0",
);
}

{s} outputs strings.

const std = @import("std");
const eql = std.mem.eql;
const expectEqualStrings = std.testing.expectEqualStrings;
const bufPrint = std.fmt.bufPrint;
test "string fmt" {
var b: [6]u8 = undefined;
const hello: [*:0]const u8 = "hello!";

try expectEqualStrings(
"hello!",
try bufPrint(&b, "{s}", .{hello}),
);
}

This list is non-exhaustive.