Kamis, 20 Oktober 2016

Perbedaan Implicit Declaration dan Explicit Declaration


Saat compile dengan GCC, seringkali muncul warning semacam ini..
kcache.c:272:2: warning: implicit declaration of function ‘fcache_add’ [-Wimplicit-function-declaration]

Jadi, apa itu impicit declaration yang diperingatkan oleh GCC tersebut? dan kenapa explicit declaration tidak pernah muncul dalam compiler warning?

Dalam mendeklarasikan sebuah symbol di C, kita dapat melakukannya dengan 2 cara.
- Implicit (Tersurat/Tidak jelas/ambigu)
- Explicit (Tersirat/Jelas)

Compiler GCC dan compiler lain pada umumnya menggunakan top-down parser. Artinya, source code diproses mulai dari membacanya dari atas lalu menuju ke bawah. Sehingga, bila kita mengakses variabel yang dideklarasikan di bawah fungsi, compiler tidak akan mengetahuinya.

/* OK */
int var = 1;
int test(){
    return var;
}

/* Error */
int test(){
    return var;
}
int var = 1;



Untuk blok fungsi, kita dapat mendeklarasikan di bawah fungsi yang membutuhkannya. Dan, compiler tidak akan mengindikasikan sebuah error, akan tetapi ia hanya akan mengeluarkan warning implicit declaration. Jadi, intinya. Implicit declaration muncul karena kita mengakses simbol yang belum pernah ditulis sebelumnya.

/* Warning implicit declaration */
int test(){
    test2();
}

void test2(){
    return;
}


/* OK */
void test2(){
    return;
}

int test(){
    test2();
}

Akan tetapi sebuah variabel, bagaimanapun harus ditulis secara explicit. Sedangkan untuk fungsi, compiler masih dapat mentolerir penulisannya yang implicit. Kenapa demikian?

Ini karena sebuah fungsi tidak akan mungkin dilakukan assignment ke dalamnya. Yang bisa dilakukan dengan fungsi adalah memanggilnya, atau mereferensikannya sebagai pointer. Sementara itu, sebuah variabel tentu akan menerima/melakukan banyak assignment, sehingga ukurannya harus jelas. Ukuran yang jelas inilah yang membutuhkan explicit declaration pada variabel.

Anda bisa mencari tahu jawaban detailnya dengan melihat tulisan sebelumnya mengenai "perbedaan tipe data pointer dan tipe data biasa secara fundamental".

/* OK */
int x = 1;
int test2(){
    return x;
}

/* Error */
int test2(){
    return x;
}
int x = 1;


Sebuah fungsi yang dideklarasikan secara implicit dapat diubah menjadi bentuk explicit dengan membuat prototype di bagian atas dari fungsi yang membutuhkannya.

/* Warning implicit declaration */
int test(){
    test2();
}

void test2(){
    return;
}

/* OK */
void test2();

int test(){
    test2();
}

void test2(){
    return;
}


Cara menulis prototype adalah dengan menulis ulang fungsi, tanpa disertai body/tubuh fungsi. Dan, jangan lupa diakhiri dengan tanda titik koma. Berikut adalah beberapa contohnya.

int test();
...
int test(){
    ....
}

int test(int a, int b, char *x, int *y);
...
int test(int a, int b, char *x, int *y){
    ....
}

Kita juga bisa menulis prototype tanpa nama parameter, lho.

int test(int, int, char *, int *);
...
int test(int a, int b, char *x, int *y){
    ....
}


Sebuah fungsi dan variabel yang ditulis dari file source lain juga dapat diakses dari file source yang berbeda. Fungsi bisa dibuat dan dipakai langsung dari source lain tanpa protoype. Namun, sekali lagi, untuk variabel kita harus membuatkan prototype untuk membuatnya explicit.


Untuk membuat fungsi eksternal menjadi explicit, kita harus menulis prototype dan disertai keyword extern. Keyword extern ini bersifat opsional untuk prototype fungsi.

/* OK */
// source_a.c
extern func_b(int, int);
//atau cukup: func_b(int, int);
extern int x;

int main(){
    func_b(1,2);
    return x+1;
}

// source_b.c
int x = 123;

int func_b(int a,int b){
    return a+b;
}

/* Implicit declaration */
// source_a.c

extern int x;

int main(){
    func_b(1,2);
    return x+1;
}

// source_b.c
int x = 123;

int func_b(int a,int b){
    return a+b;
}


/* Error */
// source_a.c

int main(){
    func_b(1,2);
    return x+1;
}

// source_b.c
int x = 123;

int func_b(int a,int b){
    return a+b;
}

Ya, saya tidak menjelaskan secara detail, tentang apa artinya impicit ataupun explicit declaration; karena itu tidak penting. Yang terpenting adalah kita tahu bagaimana tingkah laku compiler terkait dengan implicit dan explicit declaration tersebut.
Load disqus comments

0 comments