Какие платформы имеют несовместимые ABI для C и C ++?

Только что дошло до моего сведения, что стандарт C ++ говорит, что функции C и C ++ имеют разные и несовместимые типы, даже если их сигнатуры типов одинаковы (для получения дополнительной информации см. этот вопрос). Это означает, что вам технически не разрешено передавать функцию C ++ функции C, например pthread_create(),

Мне любопытно, существуют ли какие-либо платформы, в которых два ABI фактически различаются (кроме очевидных различий в названиях). В частности, кто-нибудь знает о каких-либо платформах, где эта программа C ++ не сможет скомпилироваться и запустить?

#include <assert.h>

extern "C" int run(int (*f)(int), int x) { return f(x); }

int times2(int x) { return x * 2; }

int main(int argc, char *argv[]) {
int a = times2(argc);
// This is undefined behavior according to C++ because I am passing an
// "extern C++" function pointer to an "extern C" function.
int b = run(&times2, argc);
assert(a == b);
return a;
}

21

Решение

Я не знаю ни одной платформы, где ABI отличается, но даже если соглашения о вызовах C и C ++ одинаковы, стандарт C ++ требует, чтобы компилятор выдал диагностику для программы. Связь указатель на функцию с языком C отличается от типа указатель на функцию с C ++ — связь языка, поэтому вы должны иметь возможность перегружать run() вот так:

extern "C" int run(int (*f)(int), int x) { return f(x); }
extern "C++" int run(int (*f)(int), int x) { return f(x); }

Теперь, когда вы звоните run(times) он должен вызывать второй, поэтому из этого следует, что первый не может быть вызван (нет преобразования из указателя на функцию с языком C-языка в указатель на функцию с языком C ++ — language- linkage) и поэтому оригинальный код должен вызывать диагностику компилятора. Большинство компиляторов ошибаются, например, например. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316

Нотабене Компилятор Solaris делает диагностируйте несовместимые языковые связи, как предупреждение:

"t.c", line 11: Warning (Anachronism): Formal argument f of type extern "C" int(*)(int) in call to run(extern "C" int(*)(int), int) is being passed int(*)(int).

Если вы перегружены run с extern "C++" Функция правильно вызывает extern "C++" один для run(times),

7

Другие решения

Других решений пока нет …