объявление функции не является прототипом - PullRequest
146 голосов
/ 03 сентября 2008

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

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)

У меня вопрос: как правильно объявить прототип функции?

Ответы [ 3 ]

312 голосов
/ 06 сентября 2008

В 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, он посторонний и обычно опускается.

43 голосов
/ 30 декабря 2013

Быстрый ответ: измените int testlib() на int testlib(void), чтобы указать, что функция не принимает аргументов.

A prototype по определению является объявлением функции, которое определяет тип (ы) аргумента (ов) функции.

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

int foo();

- это объявление старого стиля, в котором не указывается количество или типы аргументов. (До стандарта ANSI C 1989 года это было единственное объявление функции, доступное на языке.) Вы можете вызывать такую ​​функцию с любым произвольным числом аргументов, и компилятор не должен жаловаться - но если вызов несовместим с определением , ваша программа имеет неопределенное поведение.

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

int bar(int x, double y);

Функции без аргументов являются особым случаем. Логически, пустые скобки были бы хорошим способом указать, что аргумент, но этот синтаксис уже используется для объявлений функций старого стиля, поэтому комитет ANSI C изобрел новый синтаксис, используя ключевое слово void:

int foo(void); /* foo takes no arguments */

Функция Definition (которая включает в себя код того, что функция на самом деле делает) также предоставляет объявление . В вашем случае у вас есть что-то похожее на:

int testlib()
{
    /* code that implements testlib */
}

Это обеспечивает непрототипное объявление для testlib. Как определение, это говорит компилятору, что testlib не имеет параметров, но как объявление, он только говорит компилятору, что testlib принимает неуказанное, но фиксированное число и тип (ы) аргументов.

Если вы измените () на (void), объявление станет прототипом.

Преимущество прототипа состоит в том, что если вы случайно вызовете testlib с одним или несколькими аргументами, компилятор будет диагностировать ошибку.

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

22 голосов
/ 03 сентября 2008

Попробуйте:

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