13

I need to align a struct to a 16 byte boundary in Rust. It seems possible to give hints about alignment through the repr attribute, but it doesn't support this exact use case.

A functional test of what I'm trying to achieve is a type Foo such that

assert_eq!(mem::align_of::<Foo>(), 16);

or alternatively, a struct Bar with a field baz such that

println!("{:p}", Bar::new().baz);

always prints a number divisible by 16.

Is this currently possible in Rust? Are there any work-arounds?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Johannes Hoff
  • 3,731
  • 5
  • 31
  • 37
  • 1
    Do you mean you want to have a struct in the heap with a specific alignment? I'm not aware of alignment for stack-allocated types, but the unstable [`allocate`](http://doc.rust-lang.org/std/rt/heap/fn.allocate.html) does have an alignment argument. – Shepmaster Sep 06 '15 at 20:59
  • 1
    Also, you mention packing as decreasing alignment; do you mean to say that you need to have a *member* of a struct always at a specific alignment? You may want to bolster your question with some example code, ASCII-art memory diagrams, or more prose describing why you need to do this so that all the people smarter than I can help you. ^_^ – Shepmaster Sep 06 '15 at 21:05
  • Thanks for the feedback, @Shepmaster! I meant aligned in general, but yes, my specific use case is for the stack. I'll update my question to be clearer. – Johannes Hoff Sep 06 '15 at 23:56

2 Answers2

17

huon's answer is good, but it's out of date.

As of Rust 1.25.0, you may now align a type to N bytes using the attribute #[repr(align(N))]. It is documented under the reference's Type Layout section. Note that the alignment must be a power of 2, you may not mix align and packed representations, and aligning a type may add extra padding to the type. Here's an example of how to use the feature:

#[repr(align(64))]
struct S(u8);

fn main() {
    println!("size of S: {}", std::mem::size_of::<S>());
    println!("align of S: {}", std::mem::align_of::<S>());
}
Cornstalks
  • 37,137
  • 18
  • 79
  • 144
11

There's no way to specify alignment directly at the moment, but it is definitely desirable and useful. It is covered by issue #33626, and its RFC issue.

A current work-around to force alignment of some struct Foo to be as large as the alignment of some type T is to include a field of type [T; 0] which has size zero and so won't otherwise affect the behaviour of the struct, e.g. struct Foo { data: A, more_data: B, _align: [T; 0] }.

On nightly, this can be combined with SIMD types to get a specific high alignment, since they have alignment equal to their size (well, the next power of two), e.g.

#[repr(simd)]
struct SixteenBytes(u64, u64);

struct Foo {
    data: A,
    more_data: B,
    _align: [SixteenBytes; 0]
}
mfarrugi
  • 178
  • 11
huon
  • 94,605
  • 21
  • 231
  • 225