Kapan dan untuk tujuan apa kata kunci const harus digunakan dalam C untuk variabel?

58

Sementara kode saya ditinjau di sini masalah penggunaan constkata kunci muncul. Saya mengerti bahwa ini digunakan untuk menerapkan perilaku read-only pada variabel.

Saya bingung tentang berbagai situasi apa yang bisa bermanfaat.

  • Haruskah digunakan demi kejelasan dalam prototipe fungsi?
  • Haruskah itu digunakan sebagai langkah pengamanan selama pengembangan kode?
  • Haruskah itu digunakan dalam lingkup berbagai fungsi untuk mendeklarasikan konstanta run-time?
  • Haruskah itu digunakan sama sekali?

Pertanyaan ini hanyalah contoh dari kebingungan yang saya hadapi. Kebingungan umum adalah

  • Kapan constkata kunci yang digunakan dalam pemrograman C?
  • Apa sajakah jenis manfaat yang dapat diperoleh dengan menggunakan kata kunci ini di C?
  • Apakah ada kontra menggunakan constkata kunci?


Telah ditunjukkan bahwa pertanyaan ini mungkin terlalu luas karena semua pertanyaan ini dalam perincian pertanyaan saya. Saya hanya ingin mengklarifikasi bahwa pertanyaan-pertanyaan ini hanya untuk mengklarifikasi kebingungan mengenai pertanyaan utama.

Kapan dan untuk tujuan apa kata kunci const harus digunakan dalam C untuk variabel?

Ini juga dapat diulangi sebagai

Penggunaan constkata kunci yang tepat dalam C` dengan pro dan kontra yang sama.

Aseem Bansal
sumber
Bagi mereka yang memberikan suara untuk ditutup tolong jelaskan mengapa itu tidak termasuk dalam kategori Specific issues with software development. Saya menjadi sangat spesifik.
Aseem Bansal
Saya menduga itu karena Anda mengajukan beberapa pertanyaan dalam posting yang sama, dan karena itu pertanyaan Anda termasuk dalam kategori Terlalu Luas: "Ada terlalu banyak kemungkinan jawaban, atau jawaban yang baik akan terlalu panjang untuk format ini. Silakan tambahkan detail untuk mempersempit set jawaban atau untuk mengisolasi masalah yang dapat dijawab dalam beberapa paragraf. "
Robert Harvey
1
@RobertHarvey Semua pertanyaan ini hanya untuk menjelaskan kebingungan saya. Satu-satunya pertanyaan saya tetap judul pertanyaan ini. Jawaban yang bagus untuk itu akan mencakup semua pertanyaan terkait ini. Jadi itu tetap a specific issue. Penggunaan constkata kunci yang tepat dalam C` dengan pro dan kontra yang sama.
Aseem Bansal
@RobertHarvey Apakah sekarang lebih baik?
Aseem Bansal

Jawaban:

64

Saat mengulas kode, saya menerapkan aturan berikut:

  • Selalu gunakan constuntuk parameter fungsi yang diteruskan oleh referensi di mana fungsi tidak mengubah (atau membebaskan) data yang ditunjuk.

    int find(const int *data, size_t size, int value);
  • Selalu gunakan constuntuk konstanta yang mungkin didefinisikan menggunakan #define atau enum. Kompilator dapat menemukan data dalam memori baca-saja (ROM) sebagai hasilnya (meskipun penghubung sering merupakan alat yang lebih baik untuk tujuan ini dalam sistem tertanam).

    const double PI = 3.14;
  • Jangan pernah menggunakan const dalam prototipe fungsi untuk parameter yang diteruskan oleh nilai . Itu tidak memiliki makna dan karenanya hanya 'kebisingan'.

    // don't add const to 'value' or 'size'
    int find(const int *data, size_t size, const int value); 
    
  • Jika perlu, gunakan const volatiledi lokasi yang tidak dapat diubah oleh program tetapi mungkin masih berubah. Register perangkat keras adalah kasus penggunaan umum di sini, misalnya register status yang mencerminkan status perangkat:

    const volatile int32_t *DEVICE_STATUS =  (int32_t*) 0x100;

Penggunaan lain bersifat opsional. Misalnya, parameter ke fungsi dalam implementasi fungsi dapat ditandai sebagai const.

// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)  
{
     ... etc

atau fungsi mengembalikan nilai atau perhitungan yang diperoleh dan kemudian tidak pernah berubah:

char *repeat_str(const char *str, size_t n) 
{
    const size_t len = strlen(str);
    const size_t buf_size = 1 + (len * n);
    char *buf = malloc(buf_size);
    ...

Penggunaan ini consthanya menunjukkan bahwa Anda tidak akan mengubah variabel; mereka tidak mengubah bagaimana atau di mana variabel disimpan. Kompiler tentu saja dapat mengetahui bahwa suatu variabel tidak diubah, tetapi dengan menambahkan constAnda mengizinkannya untuk menerapkannya. Ini dapat membantu pembaca dan menambah keamanan (walaupun jika fungsi Anda cukup besar atau rumit sehingga ini membuat perbedaan besar, Anda mungkin memiliki masalah lain). Edit - mis. fungsi 200-line kode padat dengan loop bersarang dan banyak nama variabel panjang atau serupa, mengetahui bahwa variabel tertentu tidak pernah berubah mungkin memudahkan memahami secara signifikan. Fungsi-fungsi tersebut telah dirancang atau dipelihara dengan buruk.


Masalah dengan const. Anda mungkin akan mendengar istilah "keracunan const". Ini terjadi ketika menambahkan constke parameter fungsi menyebabkan 'constness' merambat.

Sunting - keracunan const: misalnya dalam fungsi:

int function_a(char * str, int n)
{
    ...
    function_b(str);
    ...
}

jika kita mengubah strke const, kita harus kemudian memastikan bahwa fuction_bjuga membutuhkan const. Dan seterusnya jika function_bmeneruskan strke function_c, dll. Seperti yang dapat Anda bayangkan ini bisa menyakitkan jika menyebar ke banyak file / modul terpisah. Jika menyebar ke fungsi yang tidak dapat diubah (misalnya perpustakaan sistem), maka pemeran menjadi perlu. Jadi percikan constkode yang ada mungkin meminta masalah. Namun dalam kode baru, yang terbaik adalah constmemenuhi syarat secara konsisten jika sesuai.

Masalah yang lebih berbahaya constadalah bahwa itu tidak dalam bahasa aslinya. Sebagai tambahan itu tidak cukup pas. Sebagai permulaan, ini memiliki dua arti (seperti dalam aturan di atas, yang berarti "Saya tidak akan mengubah ini" dan "ini tidak dapat dimodifikasi"). Tetapi lebih dari itu, itu bisa berbahaya. Sebagai contoh, kompilasi dan jalankan kode ini dan (tergantung pada kompiler / opsi) itu mungkin macet ketika dijalankan:

const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';

strchrmengembalikan char*bukan const char*. Sebagai parameter panggilan adalah constharus dilemparkan parameter panggilan untuk char*. Dan dalam hal ini yang membuang properti penyimpanan hanya baca nyata. Sunting: - ini biasanya berlaku untuk vars dalam memori hanya baca. Dengan 'ROM', maksud saya bukan hanya ROM fisik tetapi setiap memori yang dilindungi tulis, seperti yang terjadi pada bagian kode dari program yang dijalankan pada OS yang khas.

Banyak fungsi pustaka standar berperilaku dengan cara yang sama, jadi waspadalah: ketika Anda memiliki konstanta nyata (mis. Disimpan dalam ROM) Anda harus sangat berhati-hati untuk tidak kehilangan kekekalannya.

William Morris
sumber
Itu tidak benar-benar memiliki dua arti. Itu hanya berarti, seperti yang Anda katakan, " Saya tidak akan mengubah ini." Misalnya, sangat valid untuk memiliki const volatilevariabel.
detly
2
Itu berlaku untuk parameter fungsi tetapi untuk konstanta pada cakupan file, misalnya, constvariabel benar-benar hanya-baca: constmengatakan "Ini tidak dapat dimodifikasi". A const volatiledi sisi lain mengatakan "Ini tidak dapat dimodifikasi, tetapi mungkin berubah". Saya akan menambahkan menyebutkan volatile ke jawaban saya.
William Morris
Saya tidak setuju dengan komentar Anda, hanya dengan gagasan bahwa itu adalah instruksi kepada kompiler untuk memasukkannya ke dalam ROM. Itu menyiratkan semacam runtime guard terhadap perilaku tidak terdefinisi (mis. Memodifikasi konst melalui entah bagaimana), yang dapat menyebabkan kesalahpahaman seperti "mengapa saya dapat mengubah constvariabel ini melalui non- constpointer" (pertanyaan umum pada SO dan setiap forum C lainnya !). Secara keseluruhan saya suka jawaban ini :)
detly
Anda benar, "Letakkan ini di ROM" tidak akurat (meskipun ringkas :-) - Saya akan mengubahnya menjadi "Ini tidak dapat dimodifikasi", yang lebih akurat. Terima kasih atas komentar anda
William Morris
Ini adalah gambaran yang bagus. Saya ingin frase yang constmenyatakan kedua read-only Data dan membaca-hanya dilihat dari data perbedaan menjadi “ini tidak dapat diubah” versus “Anda tidak dapat mengubah ini”.
Jon Purdy
8

Secara umum dalam bahasa pemrograman apa pun dianjurkan untuk menggunakan constatau pengubah setara sejak itu

  • Hal ini dapat menjelaskan kepada penelepon bahwa apa yang mereka lewati tidak akan berubah
  • Peningkatan kecepatan potensial karena penyusun mengetahui dengan pasti dapat menghapus hal-hal tertentu yang hanya relevan jika parameter dapat berubah
  • Perlindungan dari diri Anda sendiri secara tidak sengaja mengubah nilainya
TheLQ
sumber
1

Ya, itu pada dasarnya jawaban TheLQ.

Merupakan tindakan pengamanan untuk programmer sehingga Anda tidak memodifikasi variabel, dan tidak memanggil fungsi yang dapat memodifikasinya. Dalam array atau struktur, specifier const menunjukkan bahwa nilai kontennya tidak akan diubah, dan bahkan kompiler tidak akan mengizinkan Anda untuk melakukannya. Anda masih dapat dengan mudah mengubah nilai variabel hanya dengan menggunakan gips.

Dalam apa yang biasanya saya lihat, sebagian besar digunakan untuk menambahkan nilai konstan dalam kode, dan untuk menunjukkan bahwa array atau struktur tidak akan dimodifikasi jika Anda memanggil fungsi tertentu. Bagian terakhir ini penting, karena ketika Anda memanggil fungsi yang AKAN memodifikasi array atau struktur Anda, Anda mungkin ingin mempertahankan versi aslinya, jadi Anda membuat salinan variabel dan meneruskannya ke fungsi. Jika bukan itu masalahnya, Anda tidak memerlukan salinannya, jelas, jadi misalnya Anda dapat mengubah,

int foo(Structure s);

untuk

int foo(const Structure * s);

dan tidak mendapatkan salinan overhead.

Hanya untuk menambahkan, perhatikan bahwa C memiliki aturan khusus dengan specifier const. Sebagai contoh,

int b = 1;
const int * a = &b;

tidak sama dengan

int b = 1;
int * const a = &b;

Kode pertama tidak akan memungkinkan Anda untuk memodifikasi. Dalam kasus kedua, penunjuknya konstan tetapi isinya tidak, jadi kompiler akan memungkinkan Anda untuk mengatakan * a = 3;tanpa kesalahan kompiler, tetapi Anda tidak bisa menjadikannya areferensi ke hal lain.

lgarcia
sumber
0

Sesuai dengan pernyataan TheLQ:

Ketika bekerja dengan tim pemrogram menyatakan constadalah cara yang baik untuk menunjukkan bahwa variabel tersebut tidak boleh dimodifikasi, atau hanya untuk mengingatkan diri sendiri dalam proyek-proyek besar. Ini berguna dalam arti itu, dan dapat menyelamatkan banyak sakit kepala.

David Otano
sumber