Skip to content

Commit 5318410

Browse files
committed
say more about zero-sized things
1 parent 17dab33 commit 5318410

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

reference/src/representation/structs-and-tuples.md

+30-8
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,6 @@ following:
188188

189189
[^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.
190190

191-
One deviation from C comes about with "empty structs". In Rust, a
192-
struct that contains (transitively) no data members is considered to
193-
have size zero, which is not something that exists in C. This includes
194-
a struct like `#[repr(C)] struct Foo { }`. Further, when a
195-
`#[repr(C)]` struct has a field whose type has zero-size, that field
196-
may induce padding due to its alignment, but will not otherwise affect
197-
the offsets of subsequent fields (as it takes up zero space).
198-
199191
The intention is that if one has a set of C struct declarations and a
200192
corresponding set of Rust struct declarations, all of which are tagged
201193
with `#[repr(C)]`, then the layout of those structs will all be
@@ -207,6 +199,36 @@ their layout in a C program.
207199

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

202+
**Structs with no fields.** One area where Rust layout can deviate
203+
from C/C++ -- even with `#[repr(C)]` -- comes about with "empty
204+
structs" that have no fields. In C, an empty struct declaration like
205+
`struct Foo { }` is illegal. However, both gcc and clang support
206+
options to enable such structs, and [assign them size
207+
zero](https://godbolt.org/z/AS2gdC). Rust behaves the same way --
208+
empty structs have size 0 and alignment 1 (unless an explicit
209+
`#[repr(align)]` is present). C++, in contrast, gives empty structs a
210+
size of 1.
211+
212+
**Structs of zero-size.** It is also possible to have structs that
213+
have fields but have non-zero size. In this case, the size of the
214+
struct would be zero, but its alignment may be greater. For example,
215+
`#[repr(C)] struct Foo { x: [u16; 0] }` would have an alignment of 2
216+
bytes by default. ([This matches the behavior in gcc and
217+
clang](https://godbolt.org/z/5w0gkq).)
218+
219+
**Structs with fields of zero-size.** If a `#[repr(C)]` struct
220+
containing a field of zero-size, that field does not occupy space in
221+
the struct; it can affect the offsets of subsequent fields if it
222+
induces padding due to the alignment on its type. ([This matches the
223+
behavior in gcc and clang](https://godbolt.org/z/5w0gkq).)
224+
225+
**C++ compatibility hazard.** As noted above when discussing structs
226+
with no fields, C++ treats empty structs like `struct Foo { }`
227+
differently from C and Rust. This can introduce subtle compatibility
228+
hazards. If you have an empty struct in your C++ code and you make the
229+
"naive" translation into Rust, even tagging with `#[repr(C)]` will not
230+
produce layout- or ABI-compatible results.
231+
210232
### Fixed alignment
211233

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

0 commit comments

Comments
 (0)