On Fri, 27 Jan 2023 at 14:30, Xi Ruoyao wrote: > > On Fri, 2023-01-27 at 14:07 +0000, Jonathan Wakely via Gcc-help wrote: > > I think it's safe to assume that *either* the code compiles and works > > as expected, or fails to compile. And in practice it compiles and > > works with all widely used compilers. You will not find a C++ > > implementation where the types are not compatible, but the code > > compiles anyway and then misbehaves at runtime. > > FWIW if we do "some strange thing" we may end up shooting our own foot. > Like: > > a.cc: > > #include <cstdio> > > extern "C" > { > struct A { struct {} x; int a; }; > void callback(void (*fn)(struct A *)); > } > > void f(struct A *p) > { > std::printf("%d\n", p->a); > } > > int main() > { > callback(f); > } > > b.c: > > #include <stdio.h> > > struct A { struct {} x; int a; }; > void callback(void (*fn)(struct A *)) > { > struct A foo = { .a = 42 }; > fn(&foo); > } > > This thing won't work with GCC because struct A will have different > layouts in GNU C and C++. Note that the C standard does not allow an > empty struct at all (a pedantic C compiler should reject b.c as an empty > struct violates the syntax rule of C). But GNU C supports it as an > extension. Strictly speaking, a pedantic C compiler should issue a diagnostic. It doesn't have to fail to compile. $ gcc -pedantic b.c b.c:3:12: warning: struct has no members [-Wpedantic] 3 | struct A { struct {} x; int a; }; | ^~~~~~