Apa artinya mendeklarasikan variabel volatil?

9

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?

Vikaton
sumber
1
Jika Anda membaca usia Anda di luar volatilevariabel dan dikatakan 5, dan Anda membacanya lagi tahun depan, Anda dijamin akan mendapatkan 6.
5gon12eder
@ 5gon12eder, saya mengerti volatile berarti sesuatu dapat berubah dengan cepat dan mudah tetapi, bagaimana cara kerjanya? : S
Vikaton
Juga, tergantung pada flag kompilasi Anda, variabel 'mungkin' yang tidak volatil muncul di debugger Anda (misalnya Anda menggunakan kode C + Eclipse + gdb misalnya), sebagai: 'nilai dioptimalkan' karena nilai variabel sekarang suatu tempat di register. Jika Anda tidak tahu cara menggunakan alat / fitur debugging bahasa assembly, cukup deklarasikan variabel Anda menggunakan pengubah volatile.

Jawaban:

11

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 5dari variabel dan Anda tidak mengubahnya, itu masih mengandung 5. 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 mengingat 5.

Tapi Anda bisa membacanya sebagai 5, maka mungkin sistem memuat data dari disk ke memori itu, mengubahnya menjadi 500. Jika Anda ingin program Anda membaca nilai segar 500, Anda perlu kompiler untuk tidak terlalu pintar dalam menggunakan yang sebelumnya dibaca 5. Anda harus mengatakannya untuk memuat ulang nilainya setiap waktu. Itu yang volatiledilakukannya.

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 menghapus 3 to 4dan menulis 3 to 5.

Saat Anda memasukkan skor permainan ke dalam cerita, Anda bisa:

  1. Tuliskan skor terakhir yang Anda baca,, 3 to 4anggaplah anggapan itu tidak berubah (atau tidak peduli jika itu terjadi), atau
  2. Berjalanlah ke sisi yang berlawanan dari tabel untuk membaca skor saat ini (yang kebetulan 3 to 5sekarang), dan berjalan kembali. Begitulah cara volatilevariabel bertindak.
Jerry101
sumber
11

volatile berarti dua hal:

  1. 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.

  2. 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:

i = 2; 
i = i; 

Kompiler harus menyimpan nomor dua, membaca variabel i, menyimpan variabel yang dibacanya ke i.

Ada situasi lain: Jika suatu fungsi menggunakan setjmpdan kemudian longjmpdipanggil, semua variabel lokal yang mudah menguap dari fungsi dijamin memiliki nilai terakhir disimpan - ini tidak terjadi dengan variabel lokal yang tidak mudah menguap.

gnasher729
sumber
Ada beberapa masalah halus di sini. Satu masalah yang tidak kentara adalah bahwa Anda mengkarakterisasi volatile read sebagai karakteristik variabel padahal sebenarnya itu adalah karakteristik bagaimana variabel diakses . Jika kita memiliki variabel idan nilainya pi = &i, maka x = *pitidak membaca dari i, tetapi membaca itu tidak dijamin memiliki semantik yang mudah menguap.
Eric Lippert
1
@EricLippert: Jika idinyatakan seperti volatile int iitu piharus dinyatakan sebagai volatile int *pi, dalam hal *piini adalah akses yang tidak stabil, bukan?
Jon Purdy
2

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 berkinerja statement_Asecara keseluruhan, lalu statement_B, dan akhirnya statement_C. Implementasinya tidak dapat mengingat bahwa Anda menetapkan agenilai 5. Setiap pernyataan yang referensi ageharus mengakses nilai variabel itu.

Tidak perlu volatilekata 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-ifaturan, urutan statement_A; statement_B; statement_C;mungkin dilaksanakan dengan mengeksekusi bagian statement_C, lalu bagian statement_A, lalu semua statement_B, lalu sisanya statement_A, dan akhirnya sisanya statement_C.

Mereka as-olah aturan tidak berlaku untuk volatilevariabel. Berkenaan dengan volatilevariabel 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

apa artinya ketika kompiler tidak "mengoptimalkan" alamat memori?

"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.

David Hammen
sumber
1

(non-) volatile adalah petunjuk bagi kompiler bagaimana mengoptimalkan kode (dari sudut pandang kode assembly yang dihasilkan):

  • non volatile berarti bahwa kompiler Anda saat ini memutuskan di mana variabel akan ditempatkan atau bagaimana nilai variabel-ter terferensikan ke subrutin
    • dalam alamat memori tetap,
    • pada stack [relatif terhadap prosesor saat ini stackpointer],
    • di heap [relatif terhadap basis prosesor saat ini],
    • dalam register prosesor,
    • ...
  • volatile berarti bahwa kompiler tidak dapat mengoptimalkan variabel karena sesuatu yang lain di luar kontrol main-cpu-s (yaitu pemroses io terpisah) dapat mengubah nilai ini.
k3b
sumber
0

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.

old_timer
sumber