объявление функции не является прототипом
Вопрос
У меня есть библиотека, которую я создал,
mylib.c:
#include <mylib.h>
int
testlib() {
printf("Hello world\n");
return (0);
}
mylib.h:
#include <stdio.h>
extern int testlib();
В моей программе я попытался вызвать эту библиотечную функцию:
моя программа.c:
#include <mylib.h>
int
main (int argc, char *argv[]) {
testlib();
return (0);
}
Когда я пытаюсь скомпилировать эту программу, я получаю следующую ошибку:
In file included from myprogram.c:1 mylib.h:2 warning: function declaration isn't a prototype
Я использую: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)
Мой вопрос в том, как правильно объявить прототип функции?
Решение
В C int foo()
и int foo(void)
это разные функции. int foo()
принимает произвольное количество аргументов, в то время как int foo(void)
принимает 0 аргументов.В C ++ они означают одно и то же.Я предлагаю вам использовать void
последовательно, когда вы имеете в виду отсутствие аргументов.
Если у вас есть переменная a
, extern int a;
это способ сообщить компилятору, что a
это символ, который может присутствовать в другой единице перевода (компилятор C говорит для исходного файла), не разрешайте его до времени соединения.С другой стороны, символы, являющиеся именами функций, в любом случае разрешаются во время соединения.Значение спецификатора класса хранения для функции (extern
, static
) влияет только на его видимость и extern
это значение по умолчанию, так что extern
на самом деле в этом нет необходимости.
Я предлагаю удалить extern
, это постороннее слово и обычно опускается.
Другие советы
Быстрый ответ:изменение int testlib()
Для int testlib(void)
указать, что функция не принимает аргументов.
A прототип является по определению объявлением функции, которое определяет тип (ы) аргумента (ов) функции.
Объявление функции, не являющейся прототипом, например
int foo();
это объявление старого стиля, в котором не указывается количество или типы аргументов.(До стандарта ANSI C 1989 года это был единственный вид объявления функций, доступный в языке.) Вы можете вызвать такую функцию с любым произвольным числом аргументов, и компилятор не обязан жаловаться, но если вызов несовместим с определение, ваша программа имеет неопределенное поведение.
Для функции, которая принимает один или несколько аргументов, вы можете указать тип каждого аргумента в объявлении:
int bar(int x, double y);
Функции без аргументов - это особый случай.Логически, пустые круглые скобки были бы хорошим способом указать этот аргумент, но этот синтаксис уже использовался для объявлений функций старого стиля, поэтому комитет ANSI C изобрел новый синтаксис, используя void
ключевое слово:
int foo(void); /* foo takes no arguments */
Функция определение (который включает в себя код для того, что на самом деле делает функция) также предоставляет декларация.В вашем случае у вас есть что-то похожее на:
int testlib()
{
/* code that implements testlib */
}
Это предоставляет объявление, отличное от прототипа, для testlib
.В качестве определения это сообщает компилятору, что testlib
не имеет параметров, но в качестве объявления оно только сообщает компилятору, что testlib
принимает некоторое неопределенное, но фиксированное количество и типы аргументов.
Если вы измените ()
Для (void)
объявление становится прототипом.
Преимущество прототипа заключается в том, что если вы случайно вызовете testlib
с помощью одного или нескольких аргументов компилятор диагностирует ошибку.
(В C ++ немного другие правила.В C ++ нет объявлений функций в старом стиле, а пустые круглые скобки конкретно означают, что функция не принимает аргументов.C ++ поддерживает (void)
синтаксис для обеспечения согласованности с C.Но если вам специально не нужно, чтобы ваш код компилировался как на C, так и на C ++, вам, вероятно, следует использовать ()
в C ++ и (void)
синтаксис в C.)
Попробуй:
extern int testlib(void);