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

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

Файл 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)

Как правильно объявить прототип функции?


gcc c
person Alan H    schedule 03.09.2008    source источник
comment
Удалите extern из объявления в mylib.h. Особенно, если вы пишете программу на чистом C, объявление extern там не нужно.   -  person Ryan Ahearn    schedule 03.09.2008


Ответы (3)


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

person Pramod    schedule 06.09.2008
comment
Используйте (void) в C, чтобы указать, что функция не принимает аргументов. В C ++, если вам специально не нужно, чтобы ваш код компилировался как на C, так и на C ++, просто используйте (). - person Keith Thompson; 30.12.2013
comment
@Pramod Большое спасибо за это объяснение. Гоша, это прояснило ситуацию. - person William Martens; 19.04.2021

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

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

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

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

person Keith Thompson    schedule 30.12.2013
comment
Кажется, что-то не хватает рядом с этим аргументом. - person Peter Mortensen; 10.03.2021

Пытаться:

extern int testlib(void);
person Lasse V. Karlsen    schedule 03.09.2008