3 ms·
> You only get ABIstab in C if you never change the size or layout of your structs Well, and you can append new elements to a struct and are guaranteed that th
by datenwolf 11y ago
> You only get ABIstab in C if you never change the size or layout of your structs
Well, and you can append new elements to a struct and are guaranteed that the initial sequence of common elements is identical. This is not mentioned explicitly in the C language standard, but it follows as a corollary from point 6.5.2.2.5 of the language standard:
> One special guarantee is made in order to simplify the use of unions: if a union containsseveral structures that share a common initial sequence (see below), and if the unionobject currently contains one of these structures, it is permitted to inspect the commoninitial part of any of them anywhere that a declaration of the complete type of the union isvisible. Two structures share acommon initial sequenceif corresponding members havecompatible types (and, for bit-fields, the same widths) for a sequence of one or moreinitial members.
Consider
a.h
struct a { char aye; short bee; int cee; long dee; };
a.c
#include "a.h"
int aye(struct a a) { return a.aye; }
b.h
struct b { char aye; short bee; int cee; long dee; double eee; };
b.c
#include "b.h"
int bee(struct b b) { return b.bee; }
Now if we add c.h
#include "a.h"
#include "b.h"
union ab {
struct a a;
struct b b;
};
The language standard warrants, that the common initial sequence of both structures can be used interchangeably in that union. Since however compilation units a.c and b.c are processed individually without knowledge of union ab this enforces the compiler to use the same memory layout for an initial sequence of member elements for either struct. Hence it is legal to extend structs without out altering the memory layout of the previous elements.
- nly 11y agoYou get the same guarantee in C++, as well as a language mechanism to exploit it (inheritance). You still can't pass structs by value across library boundaries in either language without fixing your ABI though. This isn't a language intrinsic problem: it boils down to the linker model, which only C and C++ share.
- datenwolf 11y ago> This isn't a language intrinsic problem: it boils down to the linker model, which only C and C++ share The linker coudln't care less about this part of the ABI (calling conventions). For example passing a function pointer to a different library (callback) the linker is completely oblivious to. Heck, the functions which pointers are being being passed around could have been compiled at runtime (JIT). Calling convention ABIs are a compiler thing, as it's the compiler that emits the machine code that's responsible for setting up the frame in which a function executes. And calling conventions is, where C and C++ differ. On the language level there are not calling conventions (how could there be, as those strongly depend on the machine architecture). However for the various operating systems out there you can find detailed calling conventions for C, but seldomly for C++. And these platform specific C calling conventions usually tightly control both how function (stack) frames are created, which registers may be clobbered, but they also control the memory layout that a C compiler for that platform shall apply on structs. For example the SysV AMD64 ABI strictly nails down the specifics of aggregate type memory layout and function parameter passing. All compilers following that spec will produce code that's compatible with each other, even across library boundaries.