Const anahtar sözcüğü değişkenler için C’de ne zaman ve hangi amaçlarla kullanılmalıdır?


58

Burada kodumu incelerken constanahtar kelimeyi kullanma sorunu ortaya çıktı. Değişkenlere salt okunur davranış uygulamak için kullanıldığını biliyorum.

Yararlı olabileceği çeşitli durumların ne olduğu konusunda kafam karıştı.

  • İşlev prototiplerinde açıklık sağlamak için kullanılmalı mıdır?
  • Kod geliştirme sırasında güvenlik önlemi olarak mı kullanılmalı?
  • Çalışma zamanı sabitlerini bildirmek için çeşitli fonksiyonlar kapsamında mı kullanılmalı?
  • Hiç kullanılmalı mı?

Bu soru sadece karşılaştığım karmaşaya örneklerdir. Genel karışıklık

  • constC programlamasında anahtar kelime ne zaman kullanılmalıdır?
  • Bu anahtar kelimeyi C ile kullanarak elde edilebilecek çeşitli avantajlar nelerdir?
  • constAnahtar kelime kullanmanın herhangi bir eksileri var mı?


Bütün bu sorulardan dolayı sorumun detayında bu sorunun çok geniş olabileceği belirtildi. Sadece bu soruların sadece ana soru ile ilgili karışıklığı açıklığa kavuşturmak olduğunu açıklamak istedim.

Const anahtar sözcüğü değişkenler için C’de ne zaman ve hangi amaçlarla kullanılmalıdır?

Olarak da tekrarlanabilir

constAnahtar kelimenin C`de uygun şekilde kullanılması ve eksileri aynıdır.


Kapatılması için oy kullananlar için lütfen neden kategoriye girmediğini açıklayın Specific issues with software development. Ben oldukça spesifik oluyorum.
Aseem Bansal

Sanırım, aynı yazıda birden fazla soru sorduğunuzdan ve bu nedenle sorunuzun Çok Geniş kategorisine girdiği için: "
Robert Harvey,

1
@RobertHarvey Bütün bu sorular sadece kafamı karıştırmak için açıklamaktır. Benim tek sorum bu sorunun adı. Buna iyi bir cevap tüm bu ilgili soruları kapsayacaktır. Bu yüzden bir kalır specific issue. constAnahtar kelimenin C`de uygun şekilde kullanılması ve eksileri aynıdır.
Aseem Bansal

@RobertHarvey Şimdi daha iyi mi?
Aseem Bansal

Yanıtlar:


64

Kodu incelerken aşağıdaki kuralları uygularım:

  • Daima const, fonksiyonun işaret ettiği verileri değiştirmediği (veya serbest bırakmadığı) referans olarak geçen fonksiyon parametreleri için kullanın.

    int find(const int *data, size_t size, int value);
  • Her zaman constbir #define veya enum kullanarak tanımlanabilecek sabitleri kullanın . Derleyici, sonuç olarak verileri salt okunur bellekte (ROM) bulabilir (her ne kadar bağlayıcı gömülü sistemlerde bu amaç için daha iyi bir araç olsa da).

    const double PI = 3.14;
  • Bir fonksiyon prototipinde , const değerini , değer tarafından iletilen bir parametre için kullanmayın . Bir anlamı yok ve bu yüzden sadece 'gürültü'.

    // don't add const to 'value' or 'size'
    int find(const int *data, size_t size, const int value); 
  • Uygun olduğunda, const volatileprogram tarafından değiştirilemeyen ancak yine de değişebilecek konumlarda kullanın . Donanım kayıtları, buradaki tipik kullanım durumudur, örneğin bir cihaz durumunu yansıtan bir durum kaydı:

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

Diğer kullanımlar isteğe bağlıdır. Örneğin, fonksiyon uygulaması içindeki bir işleve ilişkin parametreler const olarak işaretlenebilir.

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

veya işlev dönüş değerleri veya elde edilen ve ardından asla değişmeyen hesaplamalar:

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);
    ...

Bu kullanım constsadece değişkeni değiştirmeyeceğinizi gösterir; değişkenlerin nerede veya nerede saklandıklarını değiştirmezler. Derleyici elbette bir değişkenin değişmediğini çözebilir, ancak constbunu ekleyerek onu uygulamanıza izin verir. Bu, okuyucuya yardımcı olabilir ve bazı güvenlikler ekleyebilir (işlevleriniz büyük bir fark yaratacak kadar büyük veya karmaşık olsa da, muhtemelen başka sorunlarınız olabilir). Düzenleme - örn. iç içe geçmiş halkalar ve birçok uzun veya benzer değişken isimleri içeren 200 satırlı yoğun bir şekilde kodlanmış fonksiyon, belirli değişkenlerin asla değişmeyeceğini bilmek, önemli ölçüde anlamayı kolaylaştırabilir. Bu tür işlevler kötü bir şekilde tasarlanmış veya korunmuştur.


İle ilgili sorunlar const. Muhtemelen "const zehirlenmesi" terimini duyacaksınız. Bu, constbir işlev parametresine ekleme yapıldığında 'constness'ın yayılmasına neden olur.

Düzenleme - const zehirlenmesi: örneğin fonksiyonunda:

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

biz değiştirirseniz striçin const, biz o zaman sağlamalıdır fuction_bde alır const. Ve böylece eğer function_bgeçerse strüzerine function_cbirçok ayrı dosyalar / modüller içine yayar eğer bu acı olabilir Tahmin edebileceğiniz gibi, vb. Değiştirilemeyecek bir işleve yayılırsa (örneğin bir sistem kütüphanesi), o zaman alçıya ihtiyaç vardır. Bu yüzden constmevcut kodun etrafına serpmek belki sorun istiyor. Yine de yeni kodda, constuygun olan yerlerde tutarlı bir şekilde nitelendirmek en iyisidir .

Daha sinsi olan sorun const, asıl dilde olmamasıdır. Bir eklenti olarak tam olarak uymuyor. Başlangıç ​​için iki anlamı vardır (yukarıdaki kurallarda olduğu gibi, "Bunu değiştirmeyeceğim" ve "bu değiştirilemez" anlamına gelir). Fakat bundan daha fazlası tehlikeli olabilir. Örneğin, bu kodu derleyin ve çalıştırın ve (derleyiciye / seçeneklere bağlı olarak) çalıştırıldığında kilitlenebilir:

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

strchrbir char*değil döndürür const char*. Çağrı parametresi olduğu için consto olmalıdır döküm çağrı parametresi char*. Ve bu durumda, gerçek salt okunur depolama özelliğini atıyor. Düzenleme: - bu genellikle salt okunur hafızadaki değişkenler için geçerlidir. 'ROM' ile, sadece fiziksel ROM değil, tipik bir işletim sistemi üzerinde çalışan programların kod bölümünde olduğu gibi yazmaya karşı korumalı olan herhangi bir belleği kastediyorum.

Birçok standart kütüphane işlevi aynı şekilde davranır, bu yüzden dikkat edin: gerçek sabitleriniz olduğunda (yani, ROM'da saklanır), tutarlılıklarını kaybetmemek için çok dikkatli olmalısınız.


Gerçekten iki anlamı yok. Sadece, dediğin gibi, " Bunu değiştirmeyeceğim " anlamına geliyor . Örneğin, bir const volatiledeğişkene sahip olmak tamamen geçerlidir .
15'te

2
Bu fonksiyon parametrelerinin doğrudur ama Dosya kapsamında sabitleri için, örneğin bir constdeğişken gerçekten salt okunur: const"Bu diyor edemez değiştirilebilir". Bir const volatilediğer taraftan, "Bu diyor edemez değiştirilebilir, ancak değişebileceğini". Cevabıma uçucu maddelerden bahsedeceğim.
William Morris,

Yorumunuzla aynı fikirde değilim, sadece derleyiciye ROM'a koymanın bir talimatı olduğu fikrine katılıyorum. Bu, "neden bu constdeğişkeni constişaretçi olmayan bir şeyle değiştirebilirim " (SO ve diğer C forumlarında ortak bir soru olan) gibi yanlış anlamalara yol açabilen tanımsız davranışa karşı bir tür çalışma zamanı koruması anlamına gelir. !). Genel olarak olsa bu cevabı seviyorum :)
detly

Haklısın, "Bunu ROM'a koy" doğru değil (özlü olmasına rağmen :-) - Daha doğru olan "Bu değiştirilemez" olarak değiştireceğim.) Yorumlarınız için teşekkürler.
William Morris,

Bu harika bir inceleme. Ben ifade etmek istiyorum o constbeyan eder hem salt okunur veri ve salt okunur görüşlerini “Bu değişiklik yapamazsınız” karşı “bu değiştirilemez” olmanın veri farkın.
Jon Purdy

8

Genellikle herhangi bir programlama dilinde onun kullanılması önerilir constveya eşdeğer değiştirici beri

  • Arayan kişiye, geçirdikleri şeyin değişmeyeceğini açıklığa kavuşturabilir.
  • Derleyici kesin olarak bildiğinden potansiyel hız iyileştirmeleri, sadece parametre değişebiliyorsa ilgili olan bazı şeyleri çıkartabilir
  • Yanlışlıkla kendinizden koruma değeri değiştirir

1

Evet, temelde TheLQ'nin cevabı.

Programcı için bir güvenlik önlemidir, bu nedenle bir değişkeni değiştirmezsiniz ve onları değiştirebilecek işlevleri çağırmazsınız. Bir dizide veya yapıda const belirteci, içeriklerinin değerlerinin değiştirilmeyeceğini ve derleyicinin bile bunu yapmanıza izin vermeyeceğini belirtir. Ancak değişkenin değerini yalnızca bir alçıyla kolayca değiştirebilirsiniz.

Genelde gördüklerimde, çoğunlukla kodda sabit değerler eklemek ve belirli bir işlevi çağırırsanız dizinin veya yapının değiştirilmeyeceğini belirtmek için kullanılır. Bu son bölüm önemlidir, çünkü dizinizi veya yapınızı değiştirecek bir işlev çağırdığınızda, orijinal sürümü saklamak isteyebilirsiniz, böylece değişkenin bir kopyasını oluşturabilir ve sonra işlevine geçirebilirsiniz. Aksi takdirde, kopyaya gerek duymazsınız, açıkçası, örneğin,

int foo(Structure s);

için

int foo(const Structure * s);

ve kopyanın ek yükü alamaması.

Sadece eklemek için, C'nin const belirteci ile ilgili özel kuralları olduğunu unutmayın. Örneğin,

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

aynı değil

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

İlk kod değiştirmenize izin vermez. İkinci durumda, işaretçi sabittir ancak içeriği değildir, bu nedenle derleyici * a = 3;derleyici hatası vermeden söylemenize izin verir , ancak abaşka bir şeye referans veremezsiniz .


0

TheLQ'nun açıklamaları ile anlaşmaya varıldı:

Bir grup programcı ile çalışırken, beyan edilen constdeğişkenin değiştirilmemesi gerektiğini belirtmek veya sadece büyük projelerde kendinizi hatırlatmak için iyi bir yoldur. Bu anlamda kullanışlıdır ve birçok baş ağrısı kurtarabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.