Какова цель этой линии? (Объявление функции) - PullRequest
3 голосов
/ 12 января 2012

Я работаю через K & R, чтобы изучать программирование. Пока все идет хорошо, но мне неясно, какую роль играет строка кода из раздела 1.8 (функции).

В разделе 1.8 авторы показывают, как создать функцию, которая возводит одно целое в степень другого целого.

Я вставил код ниже, как это было написано в книге. Все выводит нормально. Но я не знаю, почему они включили эту строку вверху:

int power(int m, int n);

Книга не упоминает об этом, кроме того, что программа повысит целое число m до степени n. Если я удалю строку из кода, программа все равно выведет как следует.

Если я правильно понимаю, строка

int power(int base, int n)

создает функцию, а фигурные скобки внизу определяют функцию. Затем фигурные скобки под main вызывают функцию для вывода графика.

Так что, похоже, все это имеет смысл. Но я не вижу, что делает самая верхняя строка.

Это может быть посторонним, но гораздо вероятнее, что я что-то упустил. Может ли кто-нибудь объяснить мне, почему эта линия существует?

#include <stdio.h>

int power(int m, int n);

/* test power function */
main()
{
int i;

    for (i = 0; i < 10; ++i)
        printf("%d %d %d\n", i, power(2,i), power(-3, i));
    return 0;
}

/* power: raise base to n-th power; n >= 0 */

int power(int base, int n)
{
    int i, p;

    p = 1;
    for (i = 1; i <= n; ++i)
        p = p * base;
    return p;
}

Ответы [ 6 ]

7 голосов
/ 12 января 2012

Первая строка - это объявление функции. Блок кода внизу - это определение функции.

Начиная с версии стандарта ISO C 1999 года, незаконно (нарушение ограничения) вызывать функцию без видимого объявления; объявление должно предшествовать вызову.

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

Для более крупных программ обычно собирают все объявления объявлений в заголовочном файле (например, foo.h) и соответствующие определения в исходном файле (например, foo.c) , Директива #include "foo.h" используется, чтобы сделать объявления видимыми в других файлах. Вы увидите подобные вещи позже в книге.

(В 1990 и более ранних версиях C, которые охватывает K & R2, бывают случаи, когда вы можете вызвать функцию без видимого объявления - но все равно очень хорошая идея предоставить явные объявления в любом случае.)

Между прочим, объявление основной программы действительно должно быть int main(void), а не просто main().

Терминология: «прототип» - это объявление функции, которое определяет типы параметров.

int power(int base, int n);    /* a declaration that's also a prototype */
int power(int, int);           /* likewise */
int power();                   /* a declaration but not a prototype */

(Имена параметров требуются в определении, но необязательны в отдельной декларации.)

В качестве особого случая в прототипе функции без параметров используется (void), поскольку пустые скобки уже означают объявление не-прототипа. Итак, int main(void) - это прототип, а int main() - нет.

Объявления, не являющиеся прототипами, являются «устаревшими», что означает, что они могут быть теоретически удалены из будущего языкового стандарта. Но они устарели с 1989 года, и даже в новом стандарте ISO C 2011 года комитет не счел нужным их удалить.

2 голосов
/ 12 января 2012

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

Заголовочные файлы, которые #include предоставляют аналогичную функциональность, позволяющую сделать вызываемый API общедоступным, но затем код обычно предоставляется в библиотеке, а не через тот же модуль компиляции, как здесь, в этом отдельном файле. пример главы K & R Intro.

2 голосов
/ 12 января 2012
int power(int m, int n);

- это объявление функции power в форме прототипа. Объявление функции информирует компилятор о количестве параметров, которые имеет функция, типе параметров функции и типе возвращаемого значения функции.

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

1 голос
/ 12 января 2012

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

1 голос
/ 12 января 2012

Если вы не включите эту строку вверху, когда программа достигает значения power(2,i) в основной мощности, еще не было объявлено. Программы читаются сверху вниз, и, поместив объявление сверху, компилятор знает, что «определение идет».

0 голосов
/ 12 января 2012

Эта строка вверху, на которую вы ссылаетесь, является прототипом функции. ЕДИНСТВЕННАЯ вещь, для которой это нужно, состоит в том, чтобы компилятор мог проверить вашу работу, то есть убедиться, что вы используете функцию правильно, передав правильные типы и количество аргументов. Это все для чего. Вот почему вы можете удалить его, и код все еще компилируется - все, что вы делаете, удаляя его, - это удаление ссылки на компилятор, чтобы он не мог проверить вашу работу. И если вы действительно удалите его, то есть вероятность, что вы могли бы передать неправильный тип аргумента (ов) и вызвать сложную ошибку во время выполнения или сбой программы. Но, оставив его внутри, компилятор может отметить такую ​​ошибку во время компиляции, что избавит вас от некоторых неприятностей. И спасение кого-то от горя - это хорошо.

Позже, со стандартом C99, они решили сделать обязательным предоставление прототипа функции (или сначала определить функцию) для компиляции кода, что заставило компилятора проверить вашу работу.

...