@@ -188,14 +188,6 @@ following:
188
188
189
189
[ ^ 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.
190
190
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
-
199
191
The intention is that if one has a set of C struct declarations and a
200
192
corresponding set of Rust struct declarations, all of which are tagged
201
193
with ` #[repr(C)] ` , then the layout of those structs will all be
@@ -207,6 +199,38 @@ their layout in a C program.
207
199
208
200
See also the notes on [ ABI compatibility] ( #fnabi ) under the section on ` #[repr(transparent)] ` .
209
201
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, unless they are inherited from or they are fields that have
211
+ the ` [[no_unique_address]] ` attribute, in which case they do not
212
+ increase the overall size of the struct.
213
+
214
+ ** Structs of zero-size.** It is also possible to have structs that
215
+ have fields but have non-zero size. In this case, the size of the
216
+ struct would be zero, but its alignment may be greater. For example,
217
+ ` #[repr(C)] struct Foo { x: [u16; 0] } ` would have an alignment of 2
218
+ bytes by default. ([ This matches the behavior in gcc and
219
+ clang] ( https://godbolt.org/z/5w0gkq ) .)
220
+
221
+ ** Structs with fields of zero-size.** If a ` #[repr(C)] ` struct
222
+ containing a field of zero-size, that field does not occupy space in
223
+ the struct; it can affect the offsets of subsequent fields if it
224
+ induces padding due to the alignment on its type. ([ This matches the
225
+ behavior in gcc and clang] ( https://godbolt.org/z/5w0gkq ) .)
226
+
227
+ ** C++ compatibility hazard.** As noted above when discussing structs
228
+ with no fields, C++ treats empty structs like ` struct Foo { } `
229
+ differently from C and Rust. This can introduce subtle compatibility
230
+ hazards. If you have an empty struct in your C++ code and you make the
231
+ "naive" translation into Rust, even tagging with ` #[repr(C)] ` will not
232
+ produce layout- or ABI-compatible results.
233
+
210
234
### Fixed alignment
211
235
212
236
The ` #[repr(align(N))] ` attribute may be used to raise the alignment
0 commit comments