Некоторые реализации гарантируют, что вызовы между блоками компиляции будут обрабатываться способом, совместимым с двоичным интерфейсом приложений (ABI) платформы, независимо от того, что будет вызывать вызываемая функция с хранилищем, чей адрес она получает, или каким вызывающим объектомбудет делать с хранилищем, адрес которого он предоставляет, или будет делать с таким хранилищем, как только функция вернется.В таких реализациях дано что-то вроде:
// In header
typedef union FOO_PUBLIC_UNION {
uint64_t dat[4]; // Allocate space
double dummy_align1; // Force alignment
void *dummy_align2; // Force alignment
} FOO;
void act_on_foo(FOO_PUBLIC_UNION*);
// In code
FOO x = {0};
act_on_foo(&x);
в одном модуле компиляции и что-то вроде:
struct FOO_PRIVATE {
int this; float that; double whatever;
};
typedef union FOO_PUBLIC_UNION { uint64_t dat[4]; struct FOO_PRIVATE priv; } FOOPP;
void act_on_foo(FOO *p)
{
FOOPP *pp = (FOOPP*)p;
pp->priv.whatever = 1234.567;
}
при условии, что размеры FOO
и FOOPP
совпадают,Поведение вызова внешней функции из первого модуля компиляции будет определяться как распределение sizeof(FOO)
байтов, обнуление их и передача их адреса в act_on_foo
, чье поведение затем будет определяться как воздействие на байты, к которым она получает адресбезотносительно к тому, как они получили свои значения или что вызывающий будет делать с ними позже.
К сожалению, даже при том, что почти каждая реализация должна быть способна производить поведение, совместимое с вызовом функции, о которой она ничего не знает, существуетнет стандартного способа указать компилятору, что конкретный вызов функции должен рассматриваться как «непрозрачный».Реализации, предназначенные для целей, где это было бы полезно, могли и, как правило, поддерживали такую семантику с помощью «обычных» вызовов функций независимо от того, требовал ли Стандарт, и такая семантика давала бы небольшую ценность для реализаций, предназначенных только для целей, где они не были бы полезны,К сожалению, это привело к Уловке 22: у Стандарта нет оснований поручать вещи, которые реализации могут делать свободно, с мандатом или без него, в тех случаях, когда они полезны, но некоторые авторы компиляторов относятся к отсутствию Стандарта.мандат в качестве поощрения отказать в поддержке.