Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a stucts-and-tuples chapter #31

Merged
merged 19 commits into from
Oct 25, 2018
Merged
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions reference/src/representation/structs-and-tuples.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,6 @@ following:

[^aligned]: Aligning an offset O to an alignment A means to round up the offset O until it is a multiple of the alignment A.

One deviation from C comes about with "empty structs". In Rust, a
struct that contains (transitively) no data members is considered to
have size zero, which is not something that exists in C. This includes
a struct like `#[repr(C)] struct Foo { }`. Further, when a
`#[repr(C)]` struct has a field whose type has zero-size, that field
may induce padding due to its alignment, but will not otherwise affect
the offsets of subsequent fields (as it takes up zero space).

The intention is that if one has a set of C struct declarations and a
corresponding set of Rust struct declarations, all of which are tagged
with `#[repr(C)]`, then the layout of those structs will all be
Expand All @@ -207,6 +199,38 @@ their layout in a C program.

See also the notes on [ABI compatibility](#fnabi) under the section on `#[repr(transparent)]`.

**Structs with no fields.** One area where Rust layout can deviate
from C/C++ -- even with `#[repr(C)]` -- comes about with "empty
structs" that have no fields. In C, an empty struct declaration like
`struct Foo { }` is illegal. However, both gcc and clang support
options to enable such structs, and [assign them size
zero](https://godbolt.org/z/AS2gdC). Rust behaves the same way --
empty structs have size 0 and alignment 1 (unless an explicit
`#[repr(align)]` is present). C++, in contrast, gives empty structs a
size of 1, unless they are inherited from or they are fields that have
the `[[no_unique_address]]` attribute, in which case they do not
increase the overall size of the struct.

**Structs of zero-size.** It is also possible to have structs that
have fields but have non-zero size. In this case, the size of the
nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
struct would be zero, but its alignment may be greater. For example,
`#[repr(C)] struct Foo { x: [u16; 0] }` would have an alignment of 2
bytes by default. ([This matches the behavior in gcc and
clang](https://godbolt.org/z/5w0gkq).)

**Structs with fields of zero-size.** If a `#[repr(C)]` struct
containing a field of zero-size, that field does not occupy space in
the struct; it can affect the offsets of subsequent fields if it
induces padding due to the alignment on its type. ([This matches the
behavior in gcc and clang](https://godbolt.org/z/5w0gkq).)

**C++ compatibility hazard.** As noted above when discussing structs
with no fields, C++ treats empty structs like `struct Foo { }`
differently from C and Rust. This can introduce subtle compatibility
hazards. If you have an empty struct in your C++ code and you make the
"naive" translation into Rust, even tagging with `#[repr(C)]` will not
produce layout- or ABI-compatible results.

nikomatsakis marked this conversation as resolved.
Show resolved Hide resolved
### Fixed alignment

The `#[repr(align(N))]` attribute may be used to raise the alignment
Expand Down