Объявление функции не является прототипом

У меня есть библиотека, которую я создал,

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);