Perbedaan antara const & const volatile

90

Jika kita mendeklarasikan variabel karena volatilesetiap kali nilai segar diperbarui
Jika kita mendeklarasikan variabel sebagai constmaka nilai variabel itu tidak akan berubah

Lalu const volatile int temp;
Apa gunanya mendeklarasikan variabel tempseperti di atas?
Apa yang terjadi jika kita mendeklarasikan sebagai const int temp?

pengguna559208
sumber
Anda tidak akan menggunakan const volatile int temp;pada lingkup blok (yaitu di dalam { }), tidak ada gunanya di sana.
MM

Jawaban:

149

Objek yang ditandai sebagai const volatiletidak akan diizinkan untuk diubah oleh kode (kesalahan akan muncul karena constkualifikasi) - setidaknya melalui nama / penunjuk tertentu itu.

Bagian volatiledari kualifikasi berarti bahwa kompilator tidak dapat mengoptimalkan atau menyusun ulang akses ke objek tersebut.

Dalam sistem tertanam, ini biasanya digunakan untuk mengakses register perangkat keras yang dapat dibaca dan diperbarui oleh perangkat keras, tetapi tidak masuk akal untuk menulis (atau mungkin merupakan kesalahan untuk menulis).

Contohnya mungkin register status untuk port serial. Berbagai bit akan menunjukkan apakah sebuah karakter sedang menunggu untuk dibaca atau jika register pengirim siap menerima karakter baru (mis., - kosong). Setiap pembacaan register status ini dapat menghasilkan nilai yang berbeda tergantung pada apa lagi yang terjadi di perangkat keras port serial.

Tidak masuk akal untuk menulis ke register status (tergantung pada spesifikasi perangkat keras tertentu), tetapi Anda perlu memastikan bahwa setiap pembacaan register menghasilkan pembacaan perangkat keras yang sebenarnya - menggunakan nilai cache dari pembacaan sebelumnya menang ' t memberi tahu Anda tentang perubahan dalam status perangkat keras.

Contoh singkatnya:

Jika petunjuk ini tidak ditandai sebagai volatile, beberapa masalah mungkin terjadi:

  • pengujian loop while mungkin membaca register status hanya sekali, karena compiler dapat berasumsi bahwa apa pun yang ditunjukkannya tidak akan pernah berubah (tidak ada dalam pengujian while atau loop itu sendiri yang dapat mengubahnya). Jika Anda memasuki fungsi saat tidak ada karakter yang menunggu di perangkat keras UART, Anda mungkin berakhir di loop tak terbatas yang tidak pernah berhenti bahkan ketika karakter telah diterima.
  • pembacaan register penerima dapat dipindahkan oleh kompiler ke sebelum loop sementara - sekali lagi karena tidak ada fungsi yang menunjukkan bahwa *recv_regdiubah oleh loop, tidak ada alasan ia tidak dapat dibaca sebelum memasuki loop.

The volatilekualifikasi memastikan bahwa optimasi ini tidak dilakukan oleh compiler.

Michael Burr
sumber
5
1 untuk penjelasan. Dan saya punya pertanyaan: bagaimana dengan metode volatile const? Jika saya memiliki kelas, yang diakses oleh banyak utas (meskipun akses disinkronkan dengan mutex) apakah metode const saya juga harus mudah menguap (karena beberapa variabel dapat diubah oleh utas lain)
Sasa
41
  • volatile akan memberitahu compiler untuk tidak mengoptimalkan kode yang berhubungan dengan variabel, biasanya ketika kita tahu itu dapat diubah dari "luar", misalnya oleh thread lain.
  • const akan memberi tahu compiler bahwa program tersebut dilarang untuk mengubah nilai variabel.
  • const volatileadalah hal yang sangat istimewa yang mungkin Anda lihat digunakan tepat 0 kali dalam hidup Anda (tm). Seperti yang diharapkan, ini berarti program tidak dapat mengubah nilai variabel, tetapi nilai dapat dimodifikasi dari luar, sehingga tidak ada pengoptimalan yang akan dilakukan pada variabel tersebut.
mingos
sumber
12
Saya mengira bahwa volatilevariabel biasanya terjadi ketika Anda mulai mengotak-atik perangkat keras, bukan dengan utas lain. Yang pernah saya lihat const volatiledigunakan dalam hal-hal seperti register status yang dipetakan memori atau sejenisnya.
HANYA PENDAPAT SAYA yang benar
2
Tentu saja, Anda benar, multithreading hanyalah salah satu contoh, tetapi bukan satu-satunya :).
mingos
26
Jika Anda bekerja dengan sistem tertanam, Anda akan sering melihatnya.
Daniel Grillo
29

Ini bukan karena variabelnya adalah const sehingga mungkin tidak berubah antara dua titik urutan.

Constness adalah janji yang Anda buat untuk tidak mengubah nilainya, bukan bahwa nilainya tidak akan berubah.

Alexandre C.
sumber
10
Ditambah satu untuk menunjukkan bahwa constdata tidak "konstan".
Bogdan Alexandru
7

Saya perlu menggunakan ini dalam aplikasi tertanam di mana beberapa variabel konfigurasi berada di area memori flash yang dapat diperbarui oleh bootloader. Variabel config ini 'konstan' selama runtime, tetapi tanpa qualifier volatile compiler akan mengoptimalkan sesuatu seperti ini ...

... dengan menghitung nilai konstanta dan menggunakan instruksi perakitan langsung, atau memuat konstanta dari lokasi terdekat, sehingga setiap pembaruan ke nilai CANID asli di area flash konfigurasi akan diabaikan. CANID harus menjadi const volatile.

push2eject
sumber
7

Dalam C, constand volatileare type qualifier dan keduanya independen.

Pada dasarnya, constartinya nilai tersebut tidak dapat diubah oleh program.

Dan volatileartinya nilainya dapat berubah secara tiba-tiba (mungkin dari luar program).

Faktanya, Standar C memberikan contoh deklarasi yang valid yaitu constdan volatile. Contohnya adalah:

extern const volatile int real_time_clock;

di mana real_time_clockdapat dimodifikasi oleh perangkat keras, tetapi tidak dapat ditetapkan, ditambah, atau dikurangi.

Jadi kita sudah harus memperlakukan constdan volatilememisahkan. Jenis kualifikasi ini dapat diterapkan untuk struct, union, enumdan typedefjuga.

pengguna2903536
sumber
5

constArtinya variabel tidak bisa dimodifikasi oleh kode c, bukan berarti tidak bisa diubah. Artinya tidak ada instruksi yang dapat menulis ke variabel, tetapi nilainya mungkin masih berubah.

volatileberarti bahwa variabel dapat berubah setiap saat dan dengan demikian tidak ada nilai cache yang dapat digunakan; setiap akses ke variabel harus dijalankan ke alamat memorinya.

Karena pertanyaan diberi tag "tertanam" dan misalkan tempadalah variabel yang dideklarasikan pengguna, bukan register terkait perangkat keras (karena ini biasanya ditangani dalam file .h terpisah), pertimbangkan:

Prosesor tertanam yang memiliki memori data baca-tulis (RAM) volatile dan memori data read-only non-volatile, misalnya memori FLASH dalam arsitektur von-Neumann, di mana data dan ruang program berbagi data dan bus alamat yang sama.

Jika Anda menyatakan const tempmemiliki nilai (setidaknya jika berbeda dari 0), compiler akan menetapkan variabel ke alamat di ruang FLASH, karena meskipun ditetapkan ke alamat RAM, ia masih membutuhkan memori FLASH untuk menyimpan nilai awal variabel, membuat alamat RAM membuang-buang ruang karena semua operasi bersifat hanya baca.

Karena itu:

int temp;adalah variabel yang disimpan dalam RAM, diinisialisasi ke 0 saat startup (cstart), nilai cache dapat digunakan.

const int temp;adalah variabel yang disimpan dalam FLASH (read-ony), diinisialisasi ke 0 pada waktu kompilator, nilai yang di-cache dapat digunakan.

volatile int temp; adalah variabel yang disimpan dalam RAM, diinisialisasi ke 0 saat startup (cstart), nilai yang di-cache TIDAK akan digunakan.

const volatile int temp; adalah variabel yang disimpan dalam FLASH (read-ony), diinisialisasi ke 0 pada waktu kompilator, nilai yang di-cache TIDAK akan digunakan

Inilah bagian yang berguna:

Saat ini kebanyakan prosesor Embedded memiliki kemampuan untuk membuat perubahan pada memori non-volatile read-only mereka melalui modul fungsi khusus, dalam hal const int tempini dapat diubah saat runtime, meskipun tidak secara langsung. Dengan kata lain, suatu fungsi dapat mengubah nilai di alamat tempat tempdisimpan.

Contoh praktis akan digunakan tempuntuk nomor seri perangkat. Pertama kali prosesor tertanam dijalankan, tempakan sama dengan 0 (atau nilai yang dideklarasikan) dan fungsi dapat menggunakan fakta ini untuk menjalankan pengujian selama produksi dan jika berhasil, minta untuk diberi nomor seri dan ubah nilainya tempdengan cara dari fungsi khusus. Beberapa prosesor memiliki kisaran alamat khusus dengan memori OTP (one-time programmable) hanya untuk itu.

Tapi inilah perbedaannya:

Jika const int tempmerupakan ID yang dapat dimodifikasi dan bukan nomor seri yang dapat diprogram satu kali dan TIDAK dideklarasikan volatile, nilai yang di-cache dapat digunakan hingga boot berikutnya, yang berarti ID baru tersebut mungkin tidak valid hingga boot ulang berikutnya, atau lebih buruk lagi, beberapa fungsi mungkin menggunakan nilai baru sementara yang lain mungkin menggunakan nilai cache yang lebih lama sampai reboot. Jika const int tempIS dideklarasikan voltaile, perubahan ID akan segera berlaku.

Michael Kusch
sumber
Wow, jawaban ini panjang
5

Anda bisa menggunakan constdan volatilebersama - sama. Misalnya, jika 0x30diasumsikan sebagai nilai port yang diubah oleh kondisi eksternal saja, pernyataan berikut akan mencegah kemungkinan efek samping yang tidak disengaja:

Langkah
sumber
2

Sederhananya, Nilai dalam variabel 'const volatile' tidak dapat dimodifikasi secara terprogram tetapi dapat dimodifikasi oleh perangkat keras. Volatile di sini adalah untuk mencegah pengoptimalan compiler.

rajeshsam
sumber
1

Kami menggunakan kata kunci 'const' untuk variabel ketika kami tidak ingin program mengubahnya. Sedangkan ketika kita mendeklarasikan variabel 'const volatile' kita memberi tahu program untuk tidak mengubahnya dan compiler bahwa variabel ini dapat diubah secara tidak terduga dari input yang datang dari dunia luar.

Ali
sumber