Re: Empty structures have sizeof(1) in C++ now ?
- In reply to: David Chisnall : "Re: Empty structures have sizeof(1) in C++ now ?"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 20 Feb 2025 11:08:10 UTC
In fact, in C having a struct without members is undefined behavior:
> If the struct-declaration-list does not contain any named members, either directly or via an anonymous structure or anonymous union, the behavior is undefined.
However, gcc allows this as an extension, and clang has apparently followed that:
https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html
-Dimitry
> On 20 Feb 2025, at 12:03, David Chisnall <theraven@FreeBSD.org> wrote:
>
> No, that’s always been the case in C++. It comes from the rule that two allocations must have unique addresses. If a structure could have size zero, an array of these structures would have size zero and the two elements in the array would have the same address. Similarly, two struct fields could have the same address, which breaks other bits of the language (pointers to members would compare equal when they should not).
>
> C++20 introduced the no_unique_address attribute. This allows you to embed a struct in another and, if the child struct has no fields, then its address is not required to be unique and you are explicitly saying that you won’t do any of the things where this would be a problem.
>
> This lets you do things like:
>
> ```c++
> template<typename Embedded=void>
> struct SomeStructThatMayContainAnother
> {
> // Normal fields go here
>
> [[no_unique_address]]
> std::conditional_t<std::is_same_v<Embedded, void>, struct {}, Embedded> embeddedStruct;
>
> // More fields maybe here
> };
> ```
>
> In this case, `embeddedStruct` will not add any space to the parent struct if the template parameter is `void`.
>
> David
>
>> On 20 Feb 2025, at 09:40, Poul-Henning Kamp <phk@phk.freebsd.dk> wrote:
>>
>> Is this a bug ?
>>
>>
>> critter phk> cat /tmp/_.c
>>
>> #include <stdio.h>
>> struct foo {
>> };
>>
>> int
>> main(int argc, char **argv)
>> {
>> struct foo bar;
>> printf("%jd %jd\n", sizeof(struct foo), sizeof(bar));
>> return (0);
>> }
>> critter phk> cc -o /tmp/a.out /tmp/_.c
>> critter phk> /tmp/a.out
>> 0 0
>> critter phk> c++ -o /tmp/a.out /tmp/_.c
>> c++: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
>> critter phk> /tmp/a.out
>> 1 1
>>
>> --
>> Poul-Henning Kamp | UNIX since Zilog Zeus 3.20
>> phk@FreeBSD.ORG | TCP/IP since RFC 956
>> FreeBSD committer | BSD since 4.3-tahoe
>> Never attribute to malice what can adequately be explained by incompetence.
>>
>>
>
>