deklarasi fungsi bukan prototipe

158

Saya punya perpustakaan yang saya buat,

mylib.c:

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

mylib.h:

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

Dalam program saya, saya mencoba memanggil fungsi pustaka ini:

myprogram.c:

#include <mylib.h>

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

Ketika saya mencoba untuk mengkompilasi program ini, saya mendapatkan kesalahan berikut:

Dalam file termasuk dari myprogram.c: 1
mylib.h: 2 peringatan: deklarasi fungsi bukan prototipe

Saya menggunakan: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

Pertanyaan saya adalah, apa cara yang tepat untuk mendeklarasikan prototipe fungsi?

Alan H
sumber
1
Hapus extern dari deklarasi di mylib.h Terutama jika Anda menulis program C murni, deklarasi extern tidak diperlukan di sana.
Ryan Ahearn

Jawaban:

333

Dalam C int foo()dan int foo(void)berbagai fungsi. int foo()menerima sejumlah argumen sembarang, sementara int foo(void)menerima 0 argumen. Dalam C ++ artinya sama. Saya menyarankan agar Anda menggunakan voidsecara konsisten ketika Anda bermaksud tidak ada argumen.

Jika Anda memiliki variabel a, extern int a;adalah cara untuk memberi tahu kompiler bahwa itu aadalah simbol yang mungkin ada di unit terjemahan yang berbeda (C kompiler berbicara untuk file sumber), jangan menyelesaikannya sampai waktu tautan. Di sisi lain, simbol yang merupakan nama fungsi diselesaikan pada saat tautan. Arti penentu kelas penyimpanan pada fungsi ( extern, static) hanya memengaruhi visibilitasnya dan externmerupakan default, jadi externsebenarnya tidak perlu.

Saya sarankan menghapus extern, itu asing dan biasanya dihilangkan.

Pramod
sumber
9
Gunakan (void) dalam C untuk menunjukkan bahwa suatu fungsi tidak membutuhkan argumen. Di C ++, kecuali Anda secara spesifik membutuhkan kode Anda untuk mengkompilasi sebagai C dan sebagai C ++, cukup gunakan ().
Keith Thompson
49

Jawaban cepat: ubah int testlib()ke int testlib(void)untuk menentukan bahwa fungsi tidak memerlukan argumen.

Sebuah prototipe adalah dengan definisi sebuah deklarasi fungsi yang menentukan jenis (s) dari argumen fungsi (s).

Deklarasi fungsi non-prototipe seperti

int foo();

adalah deklarasi gaya lama yang tidak menentukan jumlah atau tipe argumen. (Sebelum standar ANSI C 1989, ini adalah satu-satunya jenis deklarasi fungsi yang tersedia dalam bahasa tersebut.) Anda dapat memanggil fungsi semacam itu dengan sejumlah argumen arbitrer, dan kompilator tidak diharuskan mengeluh - tetapi jika panggilan tidak konsisten dengan definisi , program Anda memiliki perilaku yang tidak ditentukan.

Untuk fungsi yang mengambil satu atau lebih argumen, Anda bisa menentukan tipe setiap argumen dalam deklarasi:

int bar(int x, double y);

Fungsi tanpa argumen adalah kasus khusus. Secara logis, tanda kurung kosong akan menjadi cara yang baik untuk menentukan argumen itu tetapi sintaks sudah digunakan untuk deklarasi fungsi gaya lama, sehingga komite ANSI C menemukan sintaks baru menggunakan voidkata kunci:

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

Definisi fungsi (yang mencakup kode untuk apa fungsi sebenarnya) juga menyediakan deklarasi . Dalam kasus Anda, Anda memiliki sesuatu yang mirip dengan:

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

Ini memberikan deklarasi non-prototipe untuk testlib. Sebagai definisi, ini memberitahu kompiler yang testlibtidak memiliki parameter, tetapi sebagai deklarasi, itu hanya memberitahu kompiler yang testlibmengambil beberapa nomor dan jenis argumen yang tidak ditentukan tetapi tetap.

Jika Anda mengubah ()ke (void)deklarasi menjadi prototipe.

Keuntungan dari prototipe adalah bahwa jika Anda secara tidak sengaja memanggil testlibdengan satu atau lebih argumen, kompiler akan mendiagnosis kesalahan tersebut.

(C ++ memiliki aturan yang sedikit berbeda. C ++ tidak memiliki deklarasi fungsi gaya lama, dan tanda kurung kosong secara khusus berarti bahwa suatu fungsi tidak memerlukan argumen. C ++ mendukung (void)sintaks untuk konsistensi dengan C. Tetapi kecuali Anda secara spesifik memerlukan kode Anda untuk mengkompilasi keduanya sebagai C dan sebagai C ++, Anda mungkin harus menggunakan ()dalam C ++ dan (void)sintaks dalam C.)

Keith Thompson
sumber
22

Mencoba:

extern int testlib(void);
Lasse V. Karlsen
sumber