Объявление функции C - PullRequest
       2

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

0 голосов
/ 21 июня 2010

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

Если да, то что это означает, что аргумент типа конвертируется в int и с плавающей запятой удваивается, если аргументы функции не определены?

Ответы [ 4 ]

4 голосов
/ 21 июня 2010

В ANSI C вам не нужно объявлять прототип функции; тем не менее, рекомендуется использовать их. Единственная причина, по которой стандарт позволяет вам их не использовать, заключается в обратной совместимости с очень старым кодом.

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

Хуже того, если функция находится в другом модуле компиляции, нет способа получить ошибку компиляции, поскольку без прототипа нет способа проверить. В этом случае, если компилятор ошибается, вы можете получить неопределенное поведение, если вызов функции помещает в стек другие типы, чем ожидает функция.

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

С помощью прототипов компилятор может проверить, правильно ли вы вызываете функцию (используя правильный номер и тип параметров).

Без прототипов возможно иметь это:

// file1.c
void doit(double d)
{
    ....
}

int sum(int a, int b, int c)
{
    return a + b + c;
}

и это:

// file2.c

// In C, this is just a declaration and not a prototype
void doit();
int sum();

int main(int argc, char *argv[])
{
    char idea[] = "use prototypes!";

    // without the prototype, the compiler will pass a char *
    // to a function that expects a double
    doit(idea);

    // and here without a prototype the compiler allows you to
    // call a function that is expecting three argument with just
    // one argument (in the calling function, args b and c will be
    // random junk)
    return sum(argc);
}
1 голос
/ 21 июня 2010

Краткий ответ: в C89 / 90 это не нужно, в C99 это необходимо.

В C89 / 90 функция не должна быть объявлена ​​для вызова. Для необъявленной функции компилятор сделает предположение о типе возвращаемого значения функции (предполагает int) и о типах параметров функции (будет выводить их из типов аргументов в точке вызова).

В C99 функция должна быть предварительно объявлена ​​для вызова. Обратите внимание, что даже в C99 нет необходимости предоставлять прототип для функции, требуется только объявление, то есть объявление не-прототипа в порядке. Это означает, что компилятору больше не нужно делать какие-либо предположения о типе возвращаемого функцией (так как объявление всегда указывает его явно), но он все равно может делать предположения о параметрах функции (если объявление не является прототипом). 1008 *

1 голос
/ 21 июня 2010

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

Я не уверен, что вы спрашиваете со второй частью. Если функция не определена, она просто не будет работать.

0 голосов
/ 21 июня 2010

Стандарт C99 в 6.5.2.2 «Вызов функции» описывает, что происходит в выражении вызова функции, в том числе, если компилятор для этой функции не видел прототипа:

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

Позже он описывает, что происходит, если выражение вызова функции не соответствует тому, как фактически определена функция:

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

Понятно, что для обеспечения правильности, используяПрототипы функций - это то, что нужно делать.Достаточно того, что C ++ сделал обязательные прототипы функций одним из «критических» изменений с помощью c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...