Back to Comprehensive Rust

Different semantics

src/unsafe-deep-dive/ffi/language-differences/semantics.md

latest1.4 KB
Original Source
<!-- Copyright 2026 Google LLC SPDX-License-Identifier: CC-BY-4.0 -->

Different semantics

<!-- mdbook tests skipped because its builds do not link libc -->
rust,editable,ignore
# // Copyright 2026 Google LLC
# // SPDX-License-Identifier: Apache-2.0
#
use std::ffi::{CStr, c_char};
use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};

unsafe extern "C" {
    /// Create a formatted time based on timestamp `t`.
    fn ctime(t: *const libc::time_t) -> *const c_char;
}

fn now_formatted() -> Result<String, SystemTimeError> {
    let now = SystemTime::now().duration_since(UNIX_EPOCH)?;
    let seconds = now.as_secs() as i64;

    // SAFETY: `seconds` is generated by the system clock and will not cause
    // overflow
    let ptr = unsafe { ctime(&seconds) };

    // SAFETY: ctime returns a pointer to a preallocated (non-null) buffer
    let ptr = unsafe { CStr::from_ptr(ptr) };

    // SAFETY: ctime uses valid UTF-8
    let fmt = ptr.to_str().unwrap();

    Ok(fmt.trim_end().to_string())
}

fn main() {
    let t = now_formatted();
    println!("{t:?}");
}
<details>

Some constructs that other languages allow cannot be expressed in the Rust language.

The ctime function modifies an internal buffer shared between calls. This cannot be represented as Rust’s lifetimes.

  • 'static does not apply, as the semantics are different
  • 'a does not apply, as the buffer outlives each call
</details>