Атрибут #[repr(C)]
Атрибут #[repr(C)] применяется к структурам, перечислениям и объединениям, чтобы задать их размещение в памяти в соответствии с правилами языка C. Это гарантирует предсказуемый порядок полей и выравнивание, что критически важно при взаимодействии с кодом на C через FFI, а также при низкоуровневой работе с памятью. Параметров у атрибута нет - он просто изменяет представление типа.
Синтаксис
#[repr(C)]
struct MyStruct
{
field1: u8,
field2: u32,
}
Пример
Давайте сравним размер структуры с атрибутом #[repr(C)] и без него. В данном случае компилятор может переупорядочить поля для оптимизации:
use std::mem::size_of;
#[repr(C)]
struct CStruct
{
a: u8,
b: u32,
c: u8,
}
struct RustStruct
{
a: u8,
b: u32,
c: u8,
}
fn main()
{
println!("CStruct: {}", size_of::<CStruct>());
println!("RustStruct: {}", size_of::<RustStruct>());
}
Результат выполнения кода:
CStruct: 12
RustStruct: 8
Пример
Давайте создадим структуру с атрибутом #[repr(C)] и передадим указатель на неё в функцию, имитирующую C-код:
#[repr(C)]
struct Point
{
x: i32,
y: i32,
}
unsafe fn process_point(ptr: *const Point) -> i32
{
(*ptr).x + (*ptr).y
}
fn main()
{
let p = Point { x: 10, y: 20 };
let res = unsafe { process_point(&p) };
println!("{}", res);
}
Результат выполнения кода:
30
Пример
Давайте применим атрибут #[repr(C)] к перечислению и проверим размер:
use std::mem::size_of;
#[repr(C)]
enum CEnum
{
A,
B,
C,
}
fn main()
{
println!("{}", size_of::<CEnum>());
}
Результат выполнения кода:
4
Смотрите также
-
атрибут
#[repr(transparent)],
который задаёт прозрачное представление -
атрибут
#[repr(packed)],
который убирает выравнивание полей -
ключевое слово
extern "C",
которое задаёт C-соглашение о вызовах -
оператор
transmute,
который позволяет преобразовывать типы