Объявление функции не является прототипом
У меня есть библиотека, которую я создал,
mylib.c:
#include <mylib.h>
int
testlib() {
printf("Hello world\n");
return (0);
}
mylib.h:
#include <stdio.h>
extern int testlib();
В моей программе я попытался вызвать эту библиотечную функцию:
myprogram.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)
Мой вопрос в том, что это правильный способ объявить прототип функции?
Ответы
Ответ 1
В C int foo()
и int foo(void)
находятся разные функции. int foo()
принимает произвольное количество аргументов, а int foo(void)
принимает 0 аргументов. В С++ они означают одно и то же. Я предлагаю вам последовательно использовать void
, если вы не имеете никаких аргументов.
Если у вас есть переменная a
, extern int a;
- это способ сообщить компилятору, что a
является символом, который может присутствовать в другой единицы перевода (компилятор C говорит о исходном файле), не разрешите его до момента соединения. С другой стороны, символы, которые являются именами функций, в любом случае разрешаются во время соединения. Значение спецификатора класса хранения для функции (extern
, static
) влияет только на ее видимость, а extern
по умолчанию, поэтому extern
фактически не нужно.
Я предлагаю удалить extern
, он посторонний и обычно опускается.
Ответ 2
Быстрый ответ: измените int testlib()
на int testlib(void)
, чтобы указать, что функция не принимает никаких аргументов.
Прототипом является определение функции, которое указывает тип аргумента (ов) функции.
Объявление не-прототипа функции, например
int foo();
- это объявление старого стиля, которое не указывает количество или типы аргументов. (До стандарта ANSI C 1989 года это был единственный вид объявления функции, доступный на этом языке.) Вы можете вызвать такую функцию с любым произвольным числом аргументов, и компилятор не должен жаловаться, но если вызов несовместим с определением, ваша программа имеет поведение undefined.
Для функции, которая принимает один или несколько аргументов, вы можете указать тип каждого аргумента в объявлении:
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
с одним или несколькими аргументами, компилятор будет диагностировать ошибку.
(С++ имеет несколько разные правила: С++ не имеет деклараций функций старого стиля, а пустые круглые скобки означают, что функция не принимает никаких аргументов. С++ поддерживает синтаксис (void)
для согласованности с C. Но если вы специально не нуждаетесь ваш код для компиляции как C, так и С++, вы должны, вероятно, использовать ()
в синтаксисе С++ и (void)
в C.)
Ответ 3
Try:
extern int testlib(void);