Прототип функции похож на объявление функции в вызывающей подпрограмме? - PullRequest
2 голосов
/ 02 ноября 2019

Если нет прототипа функции, функция неявно объявляется своим первым появлением в выражении.

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

Но компилятор всегда ограничивает вас в написании прототипа, причина в том, что он не знаеткто эта функция, потому что она объявлена ​​под main() функцией.

Вопрос: эти два эквивалентны? Будет ли запись прототипа или явное объявление функции внутри main() возвращать результат требуемый ? Как он может вернуть неправильное значение, если вы ограничены всегда использовать один из этих двух способов?

  1. , если функция объявлена ​​в том же сценарии, что и функция вызывающей функции (здесь main())
    • прототип
    • явно объявить функцию в main().
  2. , если функция объявлена ​​в другом файле
    • прототип
    • явно объявить функцию в main()

Например:

int main()
{
    double doSomething(int a);
    printf("%d", doSomething(2) );
}
double doSomething(int a)
{
     return a * 2.0;
}

против

double doSomething(int a);

int main()
{
    printf("%d", doSomething(2) );
}
double doSomething(int a)
{
     return a * 2.0;
}

Эта тема - почти то, что мне нужно, но она не отвечает на все мои вопросы. язык C - вызов функций без прототипа функции

Ответы [ 2 ]

3 голосов
/ 02 ноября 2019

Эти два объявления эквивалентны до тех пор, пока в первом случае функция doSomething не потребуется для какой-либо другой функции, кроме главной.

В этом фрагменте кода

int main()
{
    double doSomething(int a);
    //..

естьпрототип функции doSomething.

из стандарта C

Прототип функции - это объявление функции, которая объявляет типы ее параметров

То есть перед определением функции, которое также является ее объявлением, имя функции будет видно только в области действия блока main.

Рассмотрим следующую программу

#include <stdio.h>

void g( void )
{
    f( 20 );
}

int main(void) 
{
    void f( int );

    f( 10 );

    return 0;
}

void f( int x )
{
    printf( "x = %d\n", x );
}

компилятор выдаст ошибку для этого оператора

    f( 20 );

, поскольку имя f еще не объявлено.

Но это утверждение

    f( 10 );

является правильным, поскольку имя внутриобласть действия блока main уже объявлена.

Для большей ясности учтите, что функции всегда имеют связь, противоположную переменным, объявленным в области действия блока безспецификатор класса хранения.

Так что это объявление в main

    double doSomething(int a);

эквивалентно объявлению

    extern double doSomething(int a);

И компоновщик найдет определение функции, даже еслиФункция изначально объявлена ​​в области видимости блока.

1 голос
/ 02 ноября 2019

В современном C вы всегда должны объявлять функцию перед ее использованием. (Это включает в себя определение функции перед ее использованием, поскольку определение является объявлением.) Неявное объявление функций для возврата int - это поведение очень старых версий C. Его не следует использовать, компиляторы должны по крайней мере предупреждать об этом, и вы должны настроить свой компилятор так, чтобы он выдавал ошибку, а не предупреждение.

Функции обычно объявляются вне других функций. Нет ничего явно неправильного в объявлении функции внутри другой функции, но мы редко делаем это, потому что обычно мы хотим, чтобы функции были видны во всем модуле перевода, а не только в одном конкретном месте. (Единицей перевода является один исходный файл вместе со всеми файлами, включенными в него с помощью директив #include.) Имена функций подчиняются тем же правилам scope , что и имена объектов: если они появляются вне какой-либо функции, ониимеет область действия файла . Если он появляется внутри блока (список операторов внутри фигурных скобок, { … }, который включает в себя тела функций), он имеет область действия блока и виден только в этом блоке.

То, будет ли функция объявлена ​​в области видимости файла или блока, не повлияет на ее поведение.

main не является особенным в этом отношении. Скорее всего, вы спрашиваете о main, потому что вы на раннем этапе обучения программированию и в основном вызываете функции только с main. Однако функции могут вызываться из других функций, и правила о видимости области и имени не относятся к main. Если функция объявлена ​​в области видимости файла, ее имя отображается в остальной части модуля перевода. Если функция объявлена ​​в области видимости блока, внутри main или другой функции, ее имя отображается в остальной части этого блока.

Если определена функция, возвращающая double, но вы используете ее безесли вы объявите об этом, и ваш компилятор разрешит это, то вы можете ожидать, что ваша программа будет работать некорректно. Компилятор не будет автоматически конвертировать double в int. Тип функции важен, чтобы сообщить компилятору, что функция возвращает, потому что компилятор ожидает, что определенные биты будут в определенных местах, когда функция вернется, и он пишет инструкции, полагаясь на это.

...