Kata kunci 'statis' dalam C memiliki dua arti yang berbeda secara fundamental.
Lingkup Pembatas
Dalam konteks ini, 'statis' berpasangan dengan 'extern' untuk mengontrol ruang lingkup variabel atau nama fungsi. Statis menyebabkan variabel atau nama fungsi hanya tersedia dalam satu unit kompilasi dan hanya tersedia untuk kode yang ada setelah deklarasi / definisi dalam teks unit kompilasi.
Batasan ini sendiri sebenarnya hanya berarti sesuatu jika dan hanya jika Anda memiliki lebih dari satu unit kompilasi dalam proyek Anda. Jika Anda hanya memiliki satu unit kompilasi, maka ia masih melakukan hal-hal tetapi efeknya sebagian besar tidak ada gunanya (kecuali jika Anda suka menggali file objek untuk membaca apa yang dihasilkan kompiler.)
Seperti disebutkan, kata kunci ini dalam konteks ini berpasangan dengan kata kunci 'extern', yang melakukan sebaliknya - dengan membuat variabel atau nama fungsi ditautkan dengan nama yang sama yang ditemukan di unit kompilasi lainnya. Jadi, Anda dapat melihat 'statis' yang membutuhkan variabel atau nama untuk ditemukan dalam unit kompilasi saat ini, sementara 'eksternal' memungkinkan hubungan unit kompilasi silang.
Seumur Hidup Statis
Seumur hidup statis berarti bahwa variabel ada sepanjang durasi program (betapapun lama itu.) Ketika Anda menggunakan 'statis' untuk mendeklarasikan / mendefinisikan variabel dalam suatu fungsi, itu berarti bahwa variabel dibuat beberapa saat sebelum penggunaan pertama ( yang berarti, setiap kali saya mengalaminya, bahwa variabel dibuat sebelum main () dimulai) dan tidak dihancurkan setelahnya. Bahkan ketika eksekusi fungsi selesai dan kembali ke pemanggilnya. Dan seperti halnya variabel seumur hidup statis yang dinyatakan di luar fungsi, mereka diinisialisasi pada saat yang sama - sebelum main () mulai - ke nol semantik (jika tidak ada inisialisasi disediakan) atau ke nilai eksplisit yang ditentukan, jika diberikan.
Ini berbeda dari variabel fungsi tipe 'otomatis', yang dibuat baru (atau, seolah-olah baru) setiap kali fungsi dimasukkan dan kemudian dihancurkan (atau, seolah-olah dihancurkan) ketika fungsi keluar.
Berbeda dengan dampak penerapan 'statis' pada definisi variabel di luar fungsi, yang berdampak langsung pada ruang lingkupnya, menyatakan variabel fungsi (dalam suatu fungsi tubuh, jelas) sebagai 'statis' tidak memiliki dampak pada cakupannya. Lingkup ditentukan oleh fakta bahwa itu didefinisikan dalam suatu fungsi tubuh. Variabel seumur hidup statis yang didefinisikan dalam fungsi memiliki cakupan yang sama dengan variabel 'otomatis' lainnya yang didefinisikan dalam badan fungsi - ruang lingkup fungsi.
Ringkasan
Jadi kata kunci 'statis' memiliki konteks yang berbeda dengan jumlah yang berarti "makna yang sangat berbeda." Alasan itu digunakan dalam dua cara, seperti ini, adalah untuk menghindari penggunaan kata kunci lain. (Ada diskusi panjang tentang hal itu.) Ia merasa bahwa programmer dapat mentolerir penggunaan dan nilai menghindari kata kunci lain dalam bahasa lebih penting (daripada argumen sebaliknya.)
(Semua variabel yang dinyatakan di luar fungsi memiliki masa pakai statis dan tidak perlu kata kunci 'statis' untuk menjadikannya benar. Jadi, jenis kata kunci yang dibebaskan ini yang akan digunakan di sana berarti sesuatu yang sama sekali berbeda: 'hanya dapat dilihat dalam satu kompilasi) unit. "Ini semacam retas, semacamnya.)
Catatan Khusus
volatile char unsigned static PORTB @ 0x06;
Kata 'statis' di sini harus diartikan berarti bahwa penghubung tidak akan berusaha mencocokkan beberapa kejadian PORTB yang dapat ditemukan di lebih dari satu unit kompilasi (dengan asumsi kode Anda memiliki lebih dari satu.)
Ini menggunakan sintaks khusus (non-portabel) untuk menentukan "lokasi" (atau nilai numerik label yang biasanya merupakan alamat) dari PORTB. Jadi linker diberikan alamatnya dan tidak perlu menemukannya untuk itu. Jika Anda memiliki dua unit kompilasi yang menggunakan baris ini, mereka akhirnya akan menunjuk ke tempat yang sama. Jadi tidak perlu memberi label 'eksternal', di sini.
Seandainya mereka menggunakan 'eksternal' mungkin menimbulkan masalah. Linker kemudian dapat melihat (dan akan mencoba untuk mencocokkan) beberapa referensi ke PORTB yang ditemukan dalam beberapa kompilasi. Jika semuanya menentukan alamat seperti ini, dan alamatnya TIDAK sama untuk beberapa alasan [kesalahan?], Lalu apa yang harus dilakukan? Mengeluh? Atau? (Secara teknis, dengan 'extern' aturan praktisnya adalah bahwa hanya SATU unit kompilasi yang akan menentukan nilainya dan yang lain tidak.)
Hanya saja lebih mudah untuk menandainya sebagai 'statis', menghindari membuat linker khawatir tentang konflik, dan hanya menyalahkan kesalahan apa pun untuk alamat yang tidak cocok pada siapa pun yang mengubah alamat menjadi sesuatu yang tidak seharusnya.
Bagaimanapun, variabel diperlakukan sebagai 'masa hidup statis'. (Dan 'mudah berubah'.)
Sebuah deklarasi bukanlah definisi , tetapi semua definisi deklarasi
Dalam C, definisi membuat objek. Itu juga mendeklarasikannya. Tetapi deklarasi biasanya tidak (lihat catatan di bawah) membuat objek.
Berikut ini adalah definisi dan deklarasi:
static int a;
static int a = 7;
extern int b = 5;
extern int f() { return 10; }
Berikut ini bukan definisi, tetapi hanya deklarasi:
extern int b;
extern int f();
Perhatikan bahwa deklarasi tidak membuat objek aktual. Mereka hanya menyatakan rincian tentang hal itu, yang kemudian dapat digunakan oleh kompiler untuk membantu menghasilkan kode yang benar dan untuk memberikan pesan peringatan dan kesalahan, yang sesuai.
Di atas, saya katakan "biasanya," dengan penuh pertimbangan. Dalam beberapa kasus, deklarasi dapat membuat objek dan karena itu dipromosikan ke definisi oleh linker (tidak pernah oleh kompiler.) Jadi, bahkan dalam kasus yang jarang terjadi ini, kompiler C masih berpikir bahwa deklarasi hanyalah deklarasi. Ini adalah fase tautan yang membuat promosi yang diperlukan dari beberapa pernyataan. Ingatlah ini dengan cermat.
Dalam contoh di atas, jika ternyata hanya ada deklarasi untuk "extern int b;" di semua unit kompilasi tertaut, maka tautan tersebut dibebankan tanggung jawab untuk membuat definisi. Ketahuilah bahwa ini adalah acara tautan waktu. Compiler sama sekali tidak sadar, selama kompilasi. Ini hanya dapat ditentukan pada waktu tautan, jika suatu deklarasi jenis ini paling dipromosikan.
Kompiler sadar bahwa "static int a;" tidak dapat dipromosikan oleh tautan pada waktu tautan, jadi ini sebenarnya adalah definisi pada waktu kompilasi .