Декларація функції не є прототипом


158

У мене створена бібліотека,

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

При спробі компілювати цю програму я отримую таку помилку:

У файлі, включеному з myprogram.c: 1
mylib.h: 2 попередження: оголошення функції не є прототипом

Я використовую: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

Моє запитання, який правильний спосіб оголосити прототип функції?


1
Видаліть зовнішню інформацію з декларації в mylib.h Особливо, якщо ви пишете чисту програму C, зовнішня декларація там непотрібна.
Ryan Ahearn

Відповіді:


333

У С int foo()і int foo(void)є різні функції. int foo()приймає довільну кількість аргументів, тоді як int foo(void)приймає 0 аргументів. У C ++ вони означають те саме. Я пропоную вам використовувати voidпослідовно, коли ви не маєте на увазі аргументів.

Якщо у вас є змінна a, extern int a;це спосіб сказати компілятору, що aє символом, який може бути присутнім в іншому блоці перекладу (компілятор C виступає за вихідний файл), не вирішуйте його до моменту посилання. З іншого боку, символи, які є іменами функцій, так чи інакше вирішуються під час зв'язку. Значення специфікатора класу зберігання для функції ( extern, static) впливає лише на її видимість і externє за замовчуванням, тому externфактично непотрібне.

Я пропоную видалити extern, він є стороннім і, як правило, опущений.


9
Використовуйте (void) в C, щоб вказати, що функція не бере аргументів. У програмі C ++, якщо вам спеціально не потрібен код для компіляції як C, так і як C ++, просто використовуйте ().
Кіт Томпсон

49

Швидка відповідь: змініть, 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.)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.