Я встретился с работой (с XLC8 и компиляторами MSFT9) часть кода, содержа файл C++ с функцией, определяемой со связью C и ссылочным аргументом. Это прослушивает меня, поскольку ссылками является C++ только. Рассматриваемая функция вызвана из кода C, где это объявляется как взятие аргумента указателя тому же типу вместо ссылочного аргумента.
Упрощенный пример:
Файл C++:
extern "C" void f(int &i)
{
i++;
}
C файл:
void f(int *);
int main()
{
int a = 2;
f(&a);
printf("%d\n", a); /* Prints 3 */
}
Теперь, слово на улице то, что большинство компиляторов C++, под капотом, ссылки реализации точно так же, как указатель. Похож на это это и просто чистая удача причина этот код работы, или это говорит где-нибудь в спецификации C++, чем результат состоит в том при определении функции со ссылочным аргументом и связью C? Я не смог найти любую информацию об этом.
Моя копия n3000.pdf (из здесь ), в разделе 7.5— Спецификации связей :
9 . Связь из C ++ с объектами, определенными в другие языки и определенные объекты в C ++ с других языков есть определяется реализацией и зависит от языка. Только там, где стратегии размещения объектов из двух языковые реализации похожи достаточно, чтобы такая связь могла быть достигнута.
Поскольку C и C ++ - разные языки, это означает, что вы не можете полагаться на эту «особенность» общих компиляторов.
Сильнее - примечание 5 в том же разделе (выделено мной) :
Если два объявления объявляют функции с таким же именем и список-типов-параметров (8.3.5), который должен быть члены того же пространства имен или объявлять объекты с тем же именем в быть членами одного и того же пространства имен и декларации дают имена различные языковые связи, программа плохо сформирована; нет диагностики требуется, если появляются объявления в разных единицах перевода .
Итак, я бы сказал, что то, что вы сделали, не гарантирует работу в соответствии со стандартом, и компилятор не обязан печатать диагностику для приведенного вами примера, потому что объявления находятся в разных единицах перевода .
FYI, это "работает для меня" с gcc и g ++ версии 4.2.1 на Snow Leopard.
Во многих случаях, но не все, ссылка может быть реализована с помощью указателя с автоматическим разыменованием. То, что какой-либо конкретный компилятор обрабатывает функцию со связью C и параметром ссылки таким образом, не гарантируется в стандарте C ++, и вы должны рассматривать это как деталь реализации.
Нетрудно написать функцию пересылки, которая принимает указатель и вызывает вашу функцию, если вам нужно сделать это, не полагаясь на детали реализации:
void real_f(int& n) {
n++;
}
extern "C" void f(int* p) { // called from C code
real_f(*p);
}
Ссылка - это альтернативное имя для объекта. Технически в C нет ничего, что могло бы напрямую отображаться на ссылку C ++.
Очевидная реализация ссылки - это (постоянный) указатель, ссылка на который разыменовывается каждый раз, когда он используется. Итак, в зависимости от того, как ваш компилятор реализует ссылки, ваш код может работать. Но это не так.
Решение состоит в том, чтобы написать функцию C, которая принимает либо реальный объект, либо указатель на этот объект, и вызывает функцию C ++ из этого.
Вот что Бьярн Страуструп должен сказать о ссылках:
" Большинство ссылок реализуется с помощью указателя переменная; это ссылка обычно занимает одно слово в памяти. Однако ссылка, которая используется исключительно локально, может - и часто удаляется - оптимизатором ».
Например:
struct S
{
int a;
int b[100];
}; // just an example
void do_something(const vector<S>& v)
{
for (int i=0; i<v.size(); ++i)
{
int(&p)[100] = v[i].b;
for (int j=0; j<100; ++j)
cout <<p[j];
}
}
В этом случае p не нужно сохранять в памяти (возможно, он просто существует в регистре, может быть, он исчезает в инструкциях).