Объявление функции в C и C++

Я имею два файла C++, говорю file1.cpp и file2.cpp как

//file1.cpp  
#include<cstdio>  
void fun(int i)  
{  
   printf("%d\n",i);  
}

//file2.cpp
void fun(double);
int main()
{
   fun(5);
}  

Когда я компилирую их и связываю их как файлы C++, я получаю ошибку "неопределенная ссылка на забаву (дважды)".
Но когда я делаю это как C файлы, я не получаю ошибку, и 0 печатается вместо 5.
Объясните причину.
Кроме того, я хочу спросить, должны ли мы объявить функцию прежде, чем определить его потому что
Я не объявил это в file1.cpp, но никакая ошибка не прибывает в компиляцию.

7
задан Happy Mittal 4 May 2010 в 06:24
поделиться

6 ответов

Это, скорее всего, из-за перегрузки функции. При компиляции с помощью C вызов fun (double) транслируется в вызов функции сборки _fun , которая будет связана на более позднем этапе. Фактическое определение также имеет имя сборки _fun , хотя оно принимает int вместо double, и компоновщик с радостью воспользуется этим при вызове fun (double) .

C ++, с другой стороны, искажает имена сборок, поэтому вы получите что-то вроде _fun @ int для fun (int) и _fun @ double for fun (double) , чтобы перегрузка работала. Компоновщик увидит, что у них разные имена, и выдаст ошибку, что не может найти определение для fun (double) .

Что касается вашего второго вопроса, всегда рекомендуется объявлять прототипы функций, обычно это делается в заголовке, особенно если функция используется в нескольких файлах. В вашем компиляторе должна быть опция предупреждения об отсутствии прототипов, gcc использует -Wmissing-prototypes . Ваш код был бы лучше, если бы он был настроен как

// file1.hpp
#ifndef FILE1_HPP
#define FILE1_HPP
void fun(int)
#endif

// file1.c
#include "file1.hpp"
...

// file2.c
#include "file1.hpp"
int main()
{
    fun(5);
}

. Тогда в вашей программе не будет нескольких конфликтующих прототипов.

6
ответ дан 7 December 2019 в 01:18
поделиться
#include <stdio.h>

int Sum(int j, int f)
{
    int k;
    k = j + f;
    return k;
}
main()
{
   int i=3;
   int j = 6;

   int k = sum(i,j);

   printf("%d",k);
}

Вывод: 9

-3
ответ дан 7 December 2019 в 01:18
поделиться

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

#ifdef __cplusplus
extern "C" {`
#endif

внизу:

#ifdef __cplusplus
}
#endif

Это убедит его не искажать некоторые имена. {{ 1}} Посмотрите здесь

ИЛИ в своем cpp вы можете сказать

extern "C" void fun( double );
1
ответ дан 7 December 2019 в 01:18
поделиться

Это потому, что C++ позволяет перегружать функции, а C - нет. Это допустимо в C++:

double fun(int i);
double fun(double i);
...
double fun(int i) { return 1;}
double fun(double i) { return 2.1; }

но не в C.

Причина, по которой вы не можете скомпилировать это с помощью компилятора C++, заключается в том, что компилятор C++ видит объявление как double и пытается найти для него определение. В компиляторе Си вы должны получить ошибку и на это, я бы подумал, что вы не ввели код точно так, как вы сказали, когда тестировали это с компилятором Си.

Основной момент: C++ имеет перегрузку функций, C - нет.

5
ответ дан 7 December 2019 в 01:18
поделиться

Унаследованная от языка C позволяет вызывать функции, не требуя фактического объявления, видимого в переводе - это просто предполагает, что все аргументы таких функций имеют тип int.

В вашем примере C ++ допускает перегрузку и не поддерживает неявные объявления функций - компилятор использует видимую функцию fun (double), а компоновщик терпит неудачу, потому что функция fun (double) никогда не реализуется. fun (int) имеет другую сигнатуру (в C ++) и существует как уникальный символ, тогда как компилятор C (или компоновщик, в зависимости от видимости) выдает ошибку, если вы объявляете fun (int) и fun (double) как Символы C.

Именно так языки развивались с годами (или нет). Вероятно, у вашего компилятора есть предупреждение об этой проблеме (неявные объявления функций).

Вы увидите разные результаты, когда объявите функции как функции C (в вашем примере они объявлены как функции C ++ при компиляции как исходные файлы C ++).

C ++ требует, чтобы функция была объявлена ​​перед ее использованием, C - нет (если вы не укажете компилятору предупредить вас о проблеме).

1
ответ дан 7 December 2019 в 01:18
поделиться

При компиляции как C ++ вам разрешено иметь две функции с одинаковым именем (при условии, что у них разные параметры). В C ++ используется искажение имен, чтобы компоновщик мог различать их:

fun_int(int x);
fun_double(double x);

При компиляции на C существует только одна функция с определенным именем.
Когда вы компилируете file1.c, он генерирует функцию, которая считывает целое число из стека и печатает его.

Когда вы компилируете file2.c, он видит, что fun () принимает двойное значение. Таким образом, он преобразует входной параметр в двойное нажатие на стек, а затем вставляет вызов fun () в код. Поскольку функция находится в другом модуле компиляции, фактический адрес здесь не разрешается, а разрешается только при вызове компоновщика. Когда компоновщик вызывается, он видит, что вызов fun необходимо разрешить, и вставляет правильный адрес, но у него нет информации о типе, с помощью которой можно было бы проверить вызов.

Во время выполнения 5 теперь преобразуется в double и помещается в стек. Затем вызывается fun (). fun () считывает целое число из стека и затем печатает его. Поскольку double имеет макет, отличный от целого, то, что будет напечатано, будет определяться реализацией и зависит от того, как double и int размещаются в памяти.

0
ответ дан 7 December 2019 в 01:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: