Banyak program level rendah menggunakan kata kunci yang mudah menguap untuk tipe pemetaan memori dan semacamnya, namun saya agak bingung dengan apa yang BENAR - BENAR lakukan di latar belakang. Dengan kata lain, apa artinya ketika kompiler tidak "mengoptimalkan" alamat memori?
9
volatile
variabel dan dikatakan 5, dan Anda membacanya lagi tahun depan, Anda dijamin akan mendapatkan 6.Jawaban:
volatile
berarti beberapa prosesor lain atau perangkat I / O atau sesuatu dapat mengubah variabel dari bawah Anda.Dengan variabel biasa, langkah-langkah program Anda adalah satu-satunya hal yang akan mengubahnya. Jadi misalnya jika Anda membaca
5
dari variabel dan Anda tidak mengubahnya, itu masih mengandung5
. Karena Anda dapat mengandalkan itu, program Anda tidak perlu meluangkan waktu untuk membaca variabel lagi saat Anda ingin menggunakannya. Kompiler C ++ cerdas untuk menghasilkan kode yang hanya mengingat5
.Tapi Anda bisa membacanya sebagai
5
, maka mungkin sistem memuat data dari disk ke memori itu, mengubahnya menjadi500
. Jika Anda ingin program Anda membaca nilai segar500
, Anda perlu kompiler untuk tidak terlalu pintar dalam menggunakan yang sebelumnya dibaca5
. Anda harus mengatakannya untuk memuat ulang nilainya setiap waktu. Itu yangvolatile
dilakukannya.Analogi untuk anak berusia 5 tahun
Katakanlah Anda meletakkan selembar kertas besar di atas meja. Di salah satu sudut kertas, Anda menuliskan skor saat ini dari permainan yang sedang berlangsung
3 to 4
,. Kemudian Anda pergi ke sisi berlawanan dari meja dan mulai menulis cerita tentang permainan. Teman Anda yang menonton pertandingan memperbarui skor di sudut itu saat pertandingan dimulai. Dia menghapus3 to 4
dan menulis3 to 5
.Saat Anda memasukkan skor permainan ke dalam cerita, Anda bisa:
3 to 4
anggaplah anggapan itu tidak berubah (atau tidak peduli jika itu terjadi), atau3 to 5
sekarang), dan berjalan kembali. Begitulah caravolatile
variabel bertindak.sumber
volatile
berarti dua hal:Nilai variabel dapat berubah tanpa ada kode Anda yang mengubahnya. Oleh karena itu setiap kali kompiler membaca nilai variabel, ia mungkin tidak menganggap bahwa itu sama dengan terakhir kali dibaca, atau bahwa itu sama dengan nilai terakhir yang disimpan, tetapi harus dibaca lagi.
Tindakan menyimpan nilai ke variabel volatil adalah "efek samping" yang dapat diamati dari luar, sehingga kompiler tidak diizinkan untuk menghapus tindakan menyimpan nilai; misalnya jika dua nilai disimpan dalam satu baris, maka kompiler harus benar-benar menyimpan nilai dua kali.
Sebagai contoh:
Kompiler harus menyimpan nomor dua, membaca variabel i, menyimpan variabel yang dibacanya ke i.
Ada situasi lain: Jika suatu fungsi menggunakan
setjmp
dan kemudianlongjmp
dipanggil, semua variabel lokal yang mudah menguap dari fungsi dijamin memiliki nilai terakhir disimpan - ini tidak terjadi dengan variabel lokal yang tidak mudah menguap.sumber
i
dan nilainyapi = &i
, makax = *pi
tidak membaca darii
, tetapi membaca itu tidak dijamin memiliki semantik yang mudah menguap.i
dinyatakan sepertivolatile int i
itupi
harus dinyatakan sebagaivolatile int *pi
, dalam hal*pi
ini adalah akses yang tidak stabil, bukan?Penjelasan abstrak
Baik C dan C ++ memiliki konsep mesin abstrak . Ketika kode menggunakan nilai beberapa variabel, mesin abstrak mengatakan implementasinya harus mengakses nilai variabel itu. Kode formulir
statement_A; statement_B; statement_C;
harus dieksekusi persis dengan urutan yang ditentukan. Ekspresi yang umum untuk ketiga pernyataan tersebut harus dihitung ulang setiap kali terjadi.Per mesin abstrak, diberi urutan pernyataan
statement_A; statement_B; statement_C;
, implementasi harus terlebih dahulu berkinerjastatement_A
secara keseluruhan, lalustatement_B
, dan akhirnyastatement_C
. Implementasinya tidak dapat mengingat bahwa Anda menetapkanage
nilai 5. Setiap pernyataan yang referensiage
harus mengakses nilai variabel itu.Tidak perlu
volatile
kata kunci jika implementasi C atau C ++ kode dieksekusi ketat sesuai spesifikasi mesin abstrak. Mesin abstrak C dan C ++ tidak memiliki konsep register, tidak ada konsep subekspresi umum, dan urutan eksekusi ketat.Kedua bahasa juga memiliki aturan seolah-olah . Implementasi sesuai dengan standar asalkan implementasi berperilaku seolah-olah telah melakukan hal-hal sesuai spesifikasi mesin abstrak. Kompilator dapat mengasumsikan variabel non-volatil tidak mengubah nilai di antara tugas. Selama itu tidak melanggar
as-if
aturan, urutanstatement_A; statement_B; statement_C;
mungkin dilaksanakan dengan mengeksekusi bagianstatement_C
, lalu bagianstatement_A
, lalu semuastatement_B
, lalu sisanyastatement_A
, dan akhirnya sisanyastatement_C
.Mereka as-olah aturan tidak berlaku untuk
volatile
variabel. Berkenaan denganvolatile
variabel dan fungsi, suatu implementasi harus melakukan persis apa yang Anda perintahkan, dan sesuai dengan urutan Anda menyuruhnya melakukan sesuatu.Ada kerugian untuk spesifikasi mesin abstrak: Ini lambat. Salah satu aspek positif dari C dan C ++ dibandingkan dengan bahasa lain adalah mereka cukup cepat. Ini tidak akan menjadi kasus jika kode dieksekusi per mesin abstrak ini. Aturan as-if yang memungkinkan C dan C ++ menjadi sangat cepat.
ELI5 menjawab
"Mengoptimalkan pergi" alamat memori adalah konsep canggih, sesuatu yang tidak berada dalam ranah kemampuan anak berusia lima tahun. Anak lima tahun yang patuh akan melakukan persis apa yang Anda perintahkan, tidak lebih, tidak kurang. Dengan
volatile
, Anda memberi tahu implementasi untuk bertindak seperti lima: Tidak berpikir, tidak ada optimisasi mewah. Sebaliknya, implementasi harus melakukan persis apa yang diperintahkan oleh kode.sumber
(non-) volatile adalah petunjuk bagi kompiler bagaimana mengoptimalkan kode (dari sudut pandang kode assembly yang dihasilkan):
sumber
Jawabannya kelihatannya cukup konsisten tetapi melewatkan satu poin penting. Anda memberi tahu kompiler bahwa Anda ingin mengalokasikan ruang dan untuk setiap akses, baca ATAU MENULIS, Anda ingin itu melakukan akses itu. Kami tidak ingin itu mengoptimalkan akses-akses itu atau variabel itu untuk beberapa alasan.
Ya, salah satu alasannya adalah karena orang lain mungkin mengubah nilai itu untuk kita. Alasan lain adalah bahwa kita mungkin mengubah nilai itu untuk orang lain. Bahwa orang lain baik itu yang mengubahnya untuk kita atau yang kita ubah mungkin perangkat keras / logika atau perangkat lunak. Ini sering digunakan untuk menentukan akses ke kontrol dan register status dalam program tertanam logam, menulis atau membaca dari perangkat keras. Serta perangkat lunak berbicara dengan perangkat lunak yang dijelaskan dalam jawaban lain.
Anda juga akan melihat volatile yang digunakan untuk mengontrol kapan dan dalam urutan apa akses terjadi, jika Anda mencoba menentukan waktu bagian kode, dan Anda tidak menggunakan volatile variabel yang dipermasalahkan (waktu mulai, waktu selesai dan perbedaan) hanya perlu dihitung menjelang akhir kompiler bebas untuk memindahkan salah satu pengukuran waktu di sekitar (bukan tempat kami menempatkannya), bukan karena tidak stabil dengan volatile tetapi pengalaman menunjukkannya lebih kecil kemungkinannya.
Kadang-kadang, Anda akan melihat itu digunakan untuk hanya membakar waktu, lampu kilat led dasar, dunia hello bare metal, mungkin menggunakan volatile untuk variabel yang menghitung sejumlah besar hanya untuk membakar waktu mata manusia untuk melihat led ubah status. Contoh yang lebih maju kemudian menggunakan timer atau acara lain untuk membakar waktu.
sumber