Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Print to stderr without allocating

This uses:

  • A stack allocated buffer
  • The C function snprintf and write
#![allow(unused)]
fn main() {
macro_rules! eprintln {
    () => { eprintln!("") };
    ($fmt:expr $(,$arg:expr)*) => {{
        use std::ffi::{c_char, c_int};
        #[allow(non_camel_case_types)]
        type c_size_t = usize;
        #[allow(non_camel_case_types)]
        type c_ssize_t = isize;
        unsafe extern "C" {
            fn snprintf(buf: *mut c_char, buf_size: c_size_t, format: *const c_char, ...) -> c_int;
            fn write(fildes: c_int, buf: *const c_char, nbyte: c_size_t) -> c_ssize_t;
        }
        let mut buf = [0; 128];
        let fmt = concat!($fmt, "\n\0");
        // SAFETY:
        // * `buf` is a stack-allocated buffer `buf.as_mut_ptr()` is valid within this block
        // * `buf.len()` is statically known
        // * I guess ... we can't ensure the format string and passed arguments are correct, so...
        //   hope for the best!
        unsafe {
            let n = snprintf(buf.as_mut_ptr(), buf.len(), fmt.as_ptr() as _, $($arg),*);
            debug_assert!((n as usize) < buf.len());
            _ = write(2, buf.as_ptr(), n as c_size_t);
        }
    }};
}

eprintln!("I can print without alloc: %d", 42);
eprintln!("I don't need arguments either");
}
Last change: , commit: cb620d2