#macro #pointers #porting #container #struct-fields #repr #list-node

container_of

Porting C’s container_of macro to Rust

2 unstable releases

0.5.1 Feb 17, 2022
0.5.0 Feb 17, 2022
0.1.0 Feb 16, 2022

#21 in #porting

Download history 66/week @ 2025-09-16 79/week @ 2025-09-23 64/week @ 2025-09-30 29/week @ 2025-10-07 53/week @ 2025-10-14 117/week @ 2025-10-21 27/week @ 2025-10-28 108/week @ 2025-11-04 23/week @ 2025-11-11 59/week @ 2025-11-18 22/week @ 2025-11-25 61/week @ 2025-12-02 118/week @ 2025-12-09 28/week @ 2025-12-16 22/week @ 2025-12-23 70/week @ 2025-12-30

248 downloads per month
Used in 2 crates

MIT license

5KB

A Rust port of the C macro container_of.

This macro is used to convert from a pointer to a struct's field to a pointer to the struct itself. Note that the struct should be sized.

Example

#[repr(C)]
struct ListNode<T> {
	prev: Option<Box<ListNode<T>>>,
	next: Option<Box<ListNode<T>>>,
	data: T
}

let list = ListNode { prev: None, next: None, data: 123 };

// Get a pointer to the `data` from `list`.
let data_ptr = &list.data as *const i32;

// Get the container of `data_ptr`, ie the `ListNode` it was made within.
// SAFETY: `data_ptr` is a valid pointer to the `data` field of a
// `ListNode<i32>`. Additionally, `ListNode<i32>` is sized.
let list_ptr = unsafe {
	container_of::container_of!(data_ptr, ListNode<i32>, data)
};

// The resulting pointer is the same as if you just got it straight
// from the containing structure.
assert_eq!(list_ptr, &list as *const ListNode<i32>);

Safety

The following are needed to ensure soundness:

  • The $type must be a sized struct that is #[repr(C)] (or #[repr(packed)]).
  • The $ptr must be a valid pointer to the $field field of a $type. More concretely, this means that the $ptr must have originated from a valid $type struct.

Dependencies

~38KB