işlev bildirimi bir prototip değil


158

Oluşturduğum bir kütüphanem var,

mylib.c:

#include <mylib.h>
int
testlib() {
    printf("Hello world\n");
    return (0);
}

mylib.h:

#include <stdio.h>
extern int testlib();

Programımda şu kütüphane işlevini çağırmayı denedim:

myprogram.c:

#include <mylib.h>

int
main (int argc, char *argv[]) {
    testlib();
    return (0);
}

Bu programı derlemeye çalıştığımda aşağıdaki hatayı alıyorum:

Programımın içerdiği dosyada.c: 1
mylib.h: 2 uyarı: işlev bildirimi bir prototip değil

Kullanıyorum: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

Benim sorum, bir işlev prototipi bildirmenin doğru yolu nedir?


1
Exlib'i mylib.h içindeki beyandan kaldırın. Özellikle saf bir C programı yazıyorsanız, orada harici beyanı gerekli değildir.
Ryan Ahearn

Yanıtlar:


333

C int foo()ve int foo(void)farklı fonksiyonları vardır. int foo()isteğe bağlı sayıda bağımsız değişkeni int foo(void)kabul ederken , 0 bağımsız değişkeni kabul eder. C ++ ile aynı anlama gelirler. Bağımsız voiddeğişken demek istemediğinizde tutarlı bir şekilde kullanmanızı öneririm .

Eğer bir değişken varsa a, extern int a;derleyici anlatmak için bir yoldur afarklı bir çeviri birimi (kaynak dosyası için C derleyicisi konuşma) bulunabilecek bir semboldür, bağlantı saatine kadar çözmek değil. Öte yandan, işlev adları olan semboller yine de bağlantı zamanında çözülür. Bir işlev ( extern, static) üzerindeki depolama sınıfı belirticisinin anlamı yalnızca görünürlüğünü etkiler ve externvarsayılan değerdir, bu externnedenle aslında gereksizdir.

Kaldırmayı öneririm extern, yabancıdır ve genellikle atlanır.


9
Bir işlevin argüman almadığını belirtmek için (void) C harfini kullanın . C ++ 'da, kodunuzu özellikle C ve C ++ olarak derlemek için gerekmedikçe, kullanın ().
Keith Thompson

49

Hızlı yanıt: işlevin bağımsız değişken almadığını belirtmek int testlib()için int testlib(void)olarak değiştirin .

Bir prototip tanımı gereği bir işlev bildirimi olduğunu işlevin argümanı (ler) in belirtir tip (ler) i.

Prototip olmayan bir işlev bildirimi

int foo();

argüman sayısını veya türünü belirtmeyen eski stil bir bildirimdir. (1989 ANSI C standardından önce, bu, dilde mevcut olan tek tür işlev beyanıydı.) Böyle bir işlevi herhangi bir sayıda bağımsız değişkenle çağırabilirsiniz ve derleyicinin şikayet etmesi gerekmez - ancak call tanımla tutarsız , programınızın tanımlanmamış davranışı var.

Bir veya daha fazla bağımsız değişken alan bir işlev için, bildirimdeki her bağımsız değişkenin türünü belirtebilirsiniz:

int bar(int x, double y);

Bağımsız değişken içermeyen işlevler özel bir durumdur. Mantıksal olarak, boş parantezler bir bağımsız değişkeni belirtmek için iyi bir yol olurdu, ancak sözdiziminin eski stil işlev bildirimlerinde zaten kullanıldığını, bu nedenle ANSI C komitesi voidanahtar kelimeyi kullanarak yeni bir sözdizimi icat etti :

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

Bir işlev tanımı (işlevin gerçekte ne yaptığına ilişkin kodu içeren) bir bildirim de sağlar . Sizin durumunuzda, aşağıdakine benzer bir şeye sahipsiniz:

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

Bu, için prototip olmayan bir bildirim sağlar testlib. Bir tanım olarak, bu derleyiciye testlibhiçbir parametresi yoktur, ancak bir bildirim olarak, derleyiciye yalnızca testlibbelirtilmemiş ancak sabit sayıda ve türde argüman alan bir derleyici söyler .

Eğer değiştirirseniz ()için (void)beyanında bir prototip haline gelir.

Bir prototipin avantajı, yanlışlıkla testlibbir veya daha fazla bağımsız değişkenle arama yaparsanız , derleyicinin hatayı tanılamasıdır.

(C ++ biraz farklı kurallara sahiptir. C ++ 'ın eski stil işlev bildirimleri yoktur ve boş parantezler özellikle bir işlevin argüman almadığı anlamına gelir. C ++, C (void)ile tutarlılık sözdizimini destekler. C ve C ++ olarak, muhtemelen ()C ++ ve C (void)sözdizimini kullanmalısınız.)


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.