So, this question has some complex issues associated with it. But, to a first approximation, the answer is simple.
Any C struct
declaration that will be accepted by both a C compiler and a C++ compiler (which is most of them that are accepted by a C compiler) will be a 'Standard Layout Type'. This is a concept defined in the C++ standard, and C++ compilers are supposed to treat them a certain way.
In particular, a C compiler that conforms to a subset of the ABI (aka Application Binary Interface) that a C++ compiler conforms to should have the exact same memory representation for such a type.
For both Linux and Windows, the ABI is very carefully defined for both C and C++ and has been for 5-10 years now. All compilers on either platform are supposed to conform to it. So this is true for any of the common C and C++ compiler combinations. This includes Clang, g++, Visual Studio, and basically practically any compiler that isn't highly specialized that works on that platform. This doesn't necessarily mean that different versions of the standard C++ libraries have compatible implementations because (for example) the way ::std::string
has been implemented over the years (and therefor what pieces of data are actually in the string structure) has changed drastically even though the public interface hasn't changed much.
The C++ ABI is complicated by a few different factors. Among them being exception handling and function name mangling (encoding the types of function arguments in the linker symbol name for the function) conventions. Also, because of the way types are defaulted to int
in so many situations and other issues, C largely required the caller to pop arguments off the stack after the function finished because the called function couldn't really be sure of the sizes of the arguments that had been pushed on. C++ has stricter type checking, and for awhile this resulted in a 'called function pops the parameters' calling convention. I don't think this is the case anymore because I think it turned out that it was less efficient. I might be wrong though.
Now, this all goes out the window if you start using compiler-specific keywords like 'packed' or 'aligned'. Then, you should carefully consult the documentation to figure out what happens.
People have mentioned an extern "C"
declarations. These are important for interfacing between C and C++ code, but they have nothing to do with struct
layout and are not needed for this at all. What extern "C"
declarations are good for is declaring that function names and calling conventions conform to the C ABI and not the C++ ABI. This is about whether the caller pops function call parameters off the stack or the called function does, how the function name is turned into a symbol for the linker to work with, the order parameters are pushed on the stack, and so forth. Again, nothing about how structures are layed out in memory has anything to do with extern "C"
. That construct is all about functions, not struct
s.
And, to re-iterate, there's a lot of complexity here. But in the vast majority of cases, you don't need to worry about it at all. It will just work.