Учебник по C 5-е изд. внешняя связь и перегрузка функций

#c #c #overloading #external-links

Вопрос:

У меня есть это из 5-го издания C primer: Внешняя связь:

Если одна функция из набора перегруженных функций является функцией C, все остальные функции должны быть функциями C :

 class SmallInt { /* . . .   */ };
class BigNum { /* . . .   */ };
// the C function can be called from C and C   programs
// the C   functions overload that function and are callable from C  

extern "C" double calc(double);
extern SmallInt calc(const SmallIntamp;);
extern BigNum calc(const BigNumamp;);
 

Версию C calc можно вызвать из программ на C и из программ на C . Дополнительными функциями являются функции C с параметрами класса, которые могут вызываться только из программ на C . Порядок деклараций не имеет значения.

  • Итак, что я понял из этих заявлений, так это то, что я могу поместить их в заголовок. например:
     // calc.h
    #ifdef __cplusplus
    
    class SmallInt { /* . . .   */ };
    class BigNum { /* . . .   */ };      
    
    // C   functions can be overloaded
    extern SmallInt calc(const SmallIntamp;);
    extern BigNum calc(const BigNumamp;);
    extern "C" 
    
    #endif
    
    double calc(double); // C function
     
  • Итак, нужно ли мне определять версию C в исходном файле C и версию C в исходном файле C ?
     // calc.c
    #include "calc.h"
    
    double calc(double){} // do_something
    
    // calc.cxx
    #include "calc.h"
    
    SmallInt calc(const SmallIntamp;){} // do_something
    BigNum calc(const BigNumamp;){} // do_something
     
  • Теперь мне нужно скомпилировать этот способ:
      gcc print.c -c amp;amp; g   main.cxx print.cxx print.o -o prog
     
  • Это работает просто отлично, но прав ли я в своих догадках и реализации этого кода?
  • Какой смысл extern в версиях C ( calc(const SmallIntamp;) и calc(const BigNumamp;) ), если они не могут быть скомпилированы с помощью компилятора C? Большое вам спасибо!

Ответ №1:

Нет, вы можете определить все функции в исходных файлах CPP и вызвать их из C (легко, если они объявлены как имеющие связь C).

Один исходный файл, print.cxx , может иметь реализацию (тела функций) для всех трех функций. Он скомпилирован как C , и реализация double calc(double) , безусловно, может использовать C для выполнения своей работы.

Программа на языке Си может быть связана с этим .o файлом и вызвать calc(double) .

Может быть полезно создать C-вызываемый API для библиотеки C , и вы можете видеть, что это должно быть частью исходного кода C , чтобы работать.

Когда вы пишете extern "C" , вы говорите, что будете поддерживать вызов этой функции из исходного файла на языке C. Это не означает, что сама функция написана на C.

Комментарии:

1. «и позвонить им из» С » — всем им? Вам следует еще немного отполировать этот момент.

2. @StoryTeller-UnslanderMonica: Так я прав (о примерах из книг)? если у меня есть набор перегруженных функций, я могу пометить только одну из них как функцию C (связь), поэтому я могу определить только эту версию C в исходном файле.c, а остальные перегрузки в файле C ? Таким образом, я могу скомпилировать источник C с помощью компилятора C или C и только источник C с использованием компилятора C ?

3. @ItachiUchiwa — Вам не нужно компилировать исходный файл с помощью компилятора Си. Компилятор C подойдет. И в источнике может быть как extern "C" и extern "C " объявление, так и объявление. Что важно, так это то, что любой код C, включающий ваш заголовок, должен встречаться только с объявлением, дружественным к C. Так что заголовок, который у вас есть, в порядке. После того, как вы скомпилировали свой код, полученный объектный файл может быть связан независимо от исходного языка.

4. @Рассказчик-UnslanderMonica: И последнее: Какой смысл extern в calc(const SmallIntamp;) и calc(const BigNumamp;) ? Это лишнее?

5. @Итачиучива — Действительно излишне. Я предполагаю, что кто-то просто счел это более приятным для глаз, так как объявления больше синхронизируются (по количеству символов) с приведенным extern "C" выше.

Ответ №2:

Когда мы говорим о «связывании C», на самом деле мы просто заботимся о файлах заголовков. Для вызова функции на иностранном языке (например, rust/go) достаточно указать сигнатуру функции «extern C» в заголовочных файлах.

И так называемая «связь C» имеет аналог, называемый «связь C «. В последней подписи есть типы параметров, но первая — это просто простое имя функции.

Например: скомпилируйте этот файл:

 // example.cpp
#include <array>
using namespace std;
extern "C"
double funcAlpha(double, int){
    return 0;
}

double funcBeta(double, int){
    return 0;
}

int main(){
}

 

беги gcc example.cpp -o a.out amp;amp; objdump -t a.out | grep func , ты получишь

 000000000040046e g     F .text  000000000000001c              _Z8funcBetadi
0000000000400452 g     F .text  000000000000001c              funcAlpha
 

где d = двойной, i = int