Empty structs are supported in clang; I think it's a GCC extension to C. This program:
#include <stdio.h>
typedef struct {} unit;
static unit f(unit *p)
{
return (unit){};
}
static void g(unit u)
{
}
int main()
{
unit a = {}, b = {};
a = b;
f(&a);
g(b);
printf("a is at %lx, b is at %lx, "
"sizeof unit is %d\n",
(unsigned long)&a, (unsigned long)&b,
(int)sizeof(unit));
return 0;
}
compiles without complaints on my cellphone and produces the output:
a is at 7ffb39805b, b is at 7ffb39805a, sizeof unit is 0
So you can declare empty structs as variables, return them, assign them, pass them as parameters, take their addresses, create them in struct literals, and dereference pointers to them. clang is assigning different addresses to different empty-struct local variables, but presumably in an array all of them would have the same address, unlike in C++.
I wouldn't be confident that you could malloc them, and I wouldn't be surprised if passing them by value uncovered compiler divergences in the interpretation of the ABI. (I spent most of last night tracking down a bug due to LuaJIT/GCC ABI differences in the implementation of parameter passing.)
That page also says “In C++, empty structures are part of the language”, and “G++ treats empty structures as if they had a single member of type char”. I think that means the size of empty structs differs between GCC C and GCC C++.
Why couldn't you malloc them? Malloc doesn't care about types, it just wants the number of bytes, and 0 is a perfectly valid value to pass to malloc. Now, it's unspecified whether malloc will give you back a pointer distinct from all other non-freed allocated blocks or NULL, but if you don't rely on address as identity that is irrelevant.
You're right, in the standard it's implementation-defined. I mistakenly thought malloc(0) was undefined. That said, it's probably not the best-tested code path in the system library.
I mean, these are literally all special values that are explicitly called out in all the relevant standards (both ISO C and POSIX). Anyone who is competent and is writing tests for libc would surely cover that.
a is at 7ffb39805b, b is at 7ffb39805a, sizeof unit is 0
So you can declare empty structs as variables, return them, assign them, pass them as parameters, take their addresses, create them in struct literals, and dereference pointers to them. clang is assigning different addresses to different empty-struct local variables, but presumably in an array all of them would have the same address, unlike in C++.
I wouldn't be confident that you could malloc them, and I wouldn't be surprised if passing them by value uncovered compiler divergences in the interpretation of the ABI. (I spent most of last night tracking down a bug due to LuaJIT/GCC ABI differences in the implementation of parameter passing.)