Apa yang akan dicetak? 6 6 atau 6 7? Dan mengapa?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Apa yang akan dicetak? 6 6 atau 6 7? Dan mengapa?
void foo()
{
static int x = 5;
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Jawaban:
Ada dua masalah di sini, masa hidup dan ruang lingkup.
Ruang lingkup variabel adalah tempat nama variabel dapat dilihat. Di sini, x hanya terlihat di dalam fungsi foo ().
Umur variabel adalah periode keberadaannya. Jika x didefinisikan tanpa kata kunci statis, masa hidup akan dimulai dari entri ke foo () hingga kembalian dari foo (); sehingga akan diinisialisasi ulang menjadi 5 pada setiap panggilan.
Kata kunci statis bertindak untuk memperpanjang umur variabel ke masa program; misalnya inisialisasi terjadi sekali dan hanya sekali dan kemudian variabel mempertahankan nilainya - apa pun yang terjadi - pada semua panggilan mendatang ke foo ().
Hasil : 6 7
Alasan : variabel statis hanya dijalankan sekali (tidak seperti variabel otomatis) dan definisi lebih lanjut dari variabel statis akan dilewati selama waktu proses. Dan jika tidak dijalankan secara manual, ini diinisialisasi dengan nilai 0 secara otomatis. Begitu,
void foo() {
static int x = 5; // assigns value of 5 only once
x++;
printf("%d", x);
}
int main() {
foo(); // x = 6
foo(); // x = 7
return 0;
}
6 7
compiler mengatur bahwa inisialisasi variabel statis tidak terjadi setiap kali fungsi dimasukkan
Itu sama dengan memiliki program berikut:
static int x = 5;
void foo()
{
x++;
printf("%d", x);
}
int main()
{
foo();
foo();
return 0;
}
Semua yang dilakukan kata kunci statis dalam program itu adalah ia memberi tahu kompiler (pada dasarnya) 'hei, saya memiliki variabel di sini yang saya tidak ingin orang lain mengaksesnya, jangan beri tahu orang lain bahwa itu ada'.
Di dalam metode, kata kunci statis memberi tahu kompiler hal yang sama seperti di atas, tetapi juga, 'jangan beri tahu siapa pun bahwa ini ada di luar fungsi ini, seharusnya hanya dapat diakses di dalam fungsi ini'.
saya harap ini membantu
x
main; itu global. Dalam contoh aslinya x
adalah lokal ke foo, hanya terlihat saat berada di dalam blok itu, yang umumnya lebih disukai: jika foo ada untuk dipelihara x
dengan cara yang dapat diprediksi dan terlihat, maka membiarkan orang lain menyodoknya umumnya berbahaya. Sebagai manfaat lain dari menjaganya dalam ruang lingkup, foo()
itu juga tetap foo()
portabel.
c
, jadi dalam konteks ini, contoh Anda akan ilegal di lingkup global. (C membutuhkan penginisialisasi konstan untuk global, C ++ tidak).
Variabel statis di dalam fungsi memiliki umur selama program Anda berjalan. Itu tidak akan dialokasikan setiap kali fungsi Anda dipanggil dan dibatalkan alokasinya saat fungsi Anda kembali.
Deklarasi x
ada di dalam foo
tetapi x=5
inisialisasi terjadi di luar foo
!
Yang perlu kita pahami di sini adalah itu
static int x = 5;
tidak sama dengan
static int x;
x = 5;
Jawaban lain telah menggunakan kata-kata penting di sini, ruang lingkup dan masa hidup, dan menunjukkan bahwa ruang lingkup x
adalah dari titik deklarasinya di fungsi foo
hingga akhir fungsi foo
. Misalnya saya memeriksa dengan memindahkan deklarasi ke akhir fungsi, dan itu membuat pernyataan x
tidak dideklarasikan x++;
.
Jadi bagian static int x
(cakupan) dari pernyataan itu benar-benar berlaku di mana Anda membacanya, di suatu tempat DI DALAM fungsi dan hanya dari sana dan seterusnya, bukan di atasnya di dalam fungsi.
Namun bagian x = 5
(seumur hidup) dari pernyataan itu adalah inisialisasi variabel dan terjadi DI LUAR fungsi sebagai bagian dari pemuatan program. Variabel x
lahir dengan nilai 5
saat program dimuat.
Saya membaca ini di salah satu komentar: " Juga, ini tidak membahas bagian yang benar-benar membingungkan, yaitu fakta bahwa penginisialisasi dilewati pada panggilan berikutnya. " Ini dilewati pada semua panggilan. Inisialisasi variabel berada di luar kode fungsi yang sebenarnya.
Nilai 5 secara teoritis ditetapkan terlepas dari apakah foo dipanggil atau tidak, meskipun kompilator mungkin mengoptimalkan fungsi jika Anda tidak memanggilnya di mana pun. Nilai 5 harus ada dalam variabel sebelum foo dipanggil.
Di dalam foo
, pernyataan static int x = 5;
itu tidak mungkin menghasilkan kode sama sekali.
Saya menemukan alamat yang x
digunakan ketika saya memasukkan fungsi foo
ke dalam program saya, dan kemudian (dengan benar) menebak bahwa lokasi yang sama akan digunakan jika saya menjalankan program lagi. Tangkapan layar parsial di bawah ini menunjukkan yang x
memiliki nilai 5
bahkan sebelum panggilan pertama ke foo
.
Outputnya adalah 6 7
. Variabel statis (baik di dalam fungsi atau tidak) diinisialisasi tepat satu kali, sebelum fungsi apa pun dalam unit terjemahan itu dijalankan. Setelah itu, nilainya tetap dipertahankan hingga dimodifikasi.
Vadiklk,
Kenapa ...? Alasannya adalah karena variabel statis diinisialisasi hanya sekali, dan mempertahankan nilainya di seluruh program. Artinya, Anda dapat menggunakan variabel statis antara pemanggilan fungsi. juga dapat digunakan untuk menghitung "berapa kali suatu fungsi dipanggil"
main()
{
static int var = 5;
printf("%d ",var--);
if(var)
main();
}
dan jawabannya adalah 5 4 3 2 1 dan bukan 5 5 5 5 5 5 .... (loop tak terbatas) seperti yang Anda harapkan. Sekali lagi, alasannya adalah variabel statis diinisialisasi satu kali, ketika main () dipanggil berikutnya tidak akan diinisialisasi ke 5 karena sudah diinisialisasi dalam program. Jadi kita bisa mengubah nilainya tapi tidak bisa diinisialisasi ulang. Begitulah cara kerja variabel statis.
atau Anda dapat mempertimbangkan sesuai penyimpanan: variabel statis disimpan di Bagian Data program dan variabel yang disimpan di Bagian Data diinisialisasi satu kali. dan sebelum inisialisasi disimpan di bagian BSS.
Pada gilirannya, variabel Otomatis (lokal) disimpan di Stack dan semua variabel di stack diinisialisasi ulang sepanjang waktu ketika fungsi disebut sebagai FAR baru (catatan aktivasi fungsi) dibuat untuk itu.
oke untuk lebih memahami, lakukan contoh di atas tanpa "statis" dan beri tahu Anda apa yang akan menjadi outputnya. Itu membuat Anda memahami perbedaan antara keduanya.
Terima kasih Javed
Mari kita baca saja artikel Wikipedia tentang Variabel Statis ...
Variabel lokal statis: variabel yang dideklarasikan sebagai statis di dalam fungsi dialokasikan secara statis sambil memiliki cakupan yang sama dengan variabel lokal otomatis. Oleh karena itu, nilai apa pun yang dimasukkan fungsi ke dalam variabel lokal statisnya selama satu panggilan akan tetap ada saat fungsi dipanggil lagi.
Anda akan mendapatkan 6 7 dicetak sebagai, seperti yang mudah diuji, dan inilah alasannya: Ketika foo
pertama kali dipanggil, variabel statis x diinisialisasi ke 5. Kemudian dinaikkan menjadi 6 dan dicetak.
Sekarang untuk panggilan berikutnya ke foo
. Program melewatkan inisialisasi variabel statis, dan sebaliknya menggunakan nilai 6 yang ditugaskan ke x terakhir kali. Eksekusi berjalan seperti biasa, memberi Anda nilai 7.
6 dan 7 Karena variabel statis diinisialisasi hanya sekali, Jadi 5 ++ menjadi 6 pada pemanggilan pertama 6 ++ menjadi 7 pada pemanggilan ke-2 Catatan-ketika pemanggilan kedua terjadi dibutuhkan nilai x adalah 6, bukan 5 karena x adalah variabel statis.
Setidaknya dalam C ++ 11, ketika ekspresi yang digunakan untuk menginisialisasi variabel statis lokal bukanlah 'constexpr' (tidak dapat dievaluasi oleh compiler), maka inisialisasi harus terjadi selama panggilan pertama ke fungsi tersebut. Contoh paling sederhana adalah dengan langsung menggunakan parameter untuk menginisialisasi variabel statis lokal. Oleh karena itu, compiler harus mengeluarkan kode untuk menebak apakah panggilan tersebut yang pertama atau tidak, yang pada gilirannya membutuhkan variabel boolean lokal. Saya telah mengumpulkan contoh seperti itu dan memeriksa apakah ini benar dengan melihat kode assembly. Contohnya bisa seperti ini:
void f( int p )
{
static const int first_p = p ;
cout << "first p == " << p << endl ;
}
void main()
{
f(1); f(2); f(3);
}
tentu saja, jika ekspresi adalah 'constexpr', maka ini tidak diperlukan dan variabel dapat diinisialisasi pada pemuatan program dengan menggunakan nilai yang disimpan oleh compiler dalam kode assembly output.