Sabit, bir ismi ve değişmeyeceği sözü olan bir değerdir. C bunun için size üç mekanizma verir ve bunlar perde arkasında gerçekten farklı şeylerdir - biri bir değişken, biri metin değiştirme, biri de bir tam sayı türüdür.
Bir Değeri Neden Adlandırmalı
Şu iki satırı karşılaştırın:
double area = 3.14159 * r * r;
double area = PI * r * r;
İkincisi, hepsi sonradan ortaya çıkan üç sebeple daha iyidir. Sayının ne anlama geldiğini söyler. Tam olarak tek bir yerde görünür, dolayısıyla hassasiyeti değiştirmek bir arama değil, tek bir düzenlemedir. Ve PI'daki bir yazım hatası bir derleme hatasıdır, oysa 3.14195'teki bir yazım hatası yanlış bir cevaptır.
Kodun içine serpiştirilmiş isimsiz sayılara sihirli sayılar denir ve onları kaldırmak bir C programında yapabileceğiniz en ucuz iyileştirmelerden biridir.
const
const anahtar kelimesi bir değişkeni salt okunur olarak işaretler:
Atamayı yorumdan çıkarın, derleyici reddeder: assignment of read-only variable 'PI'. Derleme zamanındaki o hata, meselenin tamamıdır.
Bir const değişken gerçek bir değişkendir. Bir türü vardır, dolayısıyla derleyici onu nasıl kullandığınızı denetler. Kapsama uyar, dolayısıyla bir fonksiyonun içindeki const dışarı sızmaz. Bir adresi vardır, dolayısıyla ona bir gösterici alabilirsiniz. Ve bir hata ayıklayıcı size adını ve değerini gösterebilir.
const'a bildirim noktasında ilk değer verilmelidir - ikinci bir şans yoktur:
const int limit; /* hata (ya da sonsuza dek çöp): sonradan hiçbir şey atayamaz */
const int limit = 50; /* doğru */
#define
Ön işlemci alternatifi bir makrodur:
Bu bir değişken değildir. Derleyici çalışmadan önce ön işlemci, kaynaktaki her PI geçişini 3.14159265358979 karakterleriyle değiştirir. Derleyici ismi hiç görmez - bir #define'ın neden türü olmadığı ve hata ayıklayıcıda görünemediği tam olarak budur.
Noktalı virgül ve = olmadığına dikkat edin. Makro ham metindir, dolayısıyla şu yaygın hata:
#define MAX_USERS 100; /* noktalı virgüle dikkat */
int limit = MAX_USERS + 1; /* şuna genişler: int limit = 100; + 1; -> hata */
tanıma hiç benzemeyen bir satırda hata üretir. Makrolar için büyük harf adlandırma geleneği, tam da okuyucuların bir değiştirme olduğunu bilmesi için vardır.
Makrolar geleneksel olarak BUYUK_HARF yazılır; const değişkenler aynı fikri temsil ettiklerinde genellikle bunu izler.
Enum Sabitleri
Üçüncü biçim size adlandırılmış tam sayılardan oluşan bir küme verir:
Siz atama yapmadıkça değerler 0'dan başlar ve birer birer artar, dolayısıyla MON 0 ve FRI 4'tür. İsimsiz bir enum { ... }, düz tam sayı sabitleri için yaygın bir deyimdir.
Enum sabitlerinin her iki alternatife göre gerçek bir üstünlüğü vardır: derleyicinin anladığı derleme zamanı tam sayı sabitleridir ve hata ayıklayıcıya görünürler. Tüm hikâye C'de enum'lar sayfasında.
Hangisini Kullanmalı
| İhtiyaç | Kullanın |
|---|---|
| Türlü, kapsamlı, hata ayıklanabilir bir sabit | const |
Bir dizi boyutu, bir case etiketi, bir bit alanı genişliği | enum ya da #define |
| Bir metin sabiti | #define ya da const char * |
| Bir kayan noktalı sabit | const double |
| İlişkili tam sayı değerlerinden bir küme | enum |
Ön işlemcinin görmesi gereken her şey (#if, include korumaları) | #define |
Varsayılan const olmalıdır. Değerin derlemeden önce var olması gerektiğinde #define'a, derleme zamanı tam sayısı ya da adlandırılmış bir gruba ihtiyacınız olduğunda enum'a uzanın.
Bunun gerçekten canınızı yaktığı tek yer dizi boyutlarıdır:
C'de bir const int, bir derleme zamanı sabit ifadesi değil, salt okunur bir değişkendir. Bir fonksiyonun içinde C99, int local[const_size]'ı değişken uzunluklu bir dizi yaparak kabul eder; dosya kapsamında, bir struct içinde ya da bir case etiketi olarak doğrudan reddedilir. enum ve #define her yerde çalışır.
(Bu, const int'in bir sabit ifadesi olduğu C++'tan gerçek farklardan biridir. Diller arasında dolaşan kod buna takılır.)
Göstericilerle const
const ve göstericiler üç şekilde birleşir ve anlamları birbirinin yerine geçmez. Bildirimi isimden dışarı doğru okuyun:
const char *p; /* p, değiştirilmemesi gereken char'ları gösterir */
char * const q; /* q'nun kendisi yeniden yönlendirilemez; char'lar değişebilir */
const char * const r; /* ne gösterici ne de char'lar değişebilir */
const char * biçimi en çok yazacağınız olandır, çünkü bir metni değiştirmeden okuyan bir fonksiyon parametresi için doğru türdür:
Salt okunur bir parametreye const eklemek hiçbir şeye mal olmaz ve sözleşmeyi derleyicinin uyguladığı bir biçimde belgeler. Her yerde yapmaya değer.
Metin Sabitleri Fiilen const'tur
const'ın yakalamak için var olduğu ince bir tuzak:
char *s = "hello"; /* geçerli C, ama s salt okunur belleği gösterir */
s[0] = 'H'; /* tanımsız davranış - genellikle bir çökme */
Metin sabitleri, çalıştırılabilir dosyanın salt okunur bir bölümünde yaşar. O göstericiden yazmak tipik olarak segfault verir. Göstericiyi const char *s = "hello"; diye bildirmek, derleyicinin çalışma zamanında çökmesine izin vermek yerine atamayı reddetmesini sağlar.
Değiştirilebilir bir metne ihtiyacınız varsa onu bir diziye kopyalayın:
Sıkça Sorulan Sorular
C'de bir sabit nasıl tanımlanır?
Bir bildirime const ekleyin ve bir değer verin: const double PI = 3.14159;. Derleyici o zaman ona atama yapma girişimlerini reddeder. Daha eski alternatif, bunun yerine metin değiştirme yapan bir ön işlemci makrosudur: #define PI 3.14159.
C'de const ile #define arasındaki fark nedir?
const, derleyicinin bildiği gerçek, türlü bir değişken oluşturur; dolayısıyla tür denetimi yapılır, hata ayıklayıcıda görünür ve kapsama uyar. #define, derlemeden önce yapılan saf metin değiştirmedir - türü yoktur, kapsamı yoktur ve hata ayıklarken incelenemez. Değere derleme zamanı sabiti gerektiren bir bağlamda ihtiyacınız yoksa const'ı tercih edin.
C'de bir const değişken dizi boyutu olarak kullanılabilir mi?
Dosya kapsamında sabit boyutlu bir dizi için hayır. const int N = 10; int arr[N];, C99'da değişken uzunluklu bir dizidir (bir fonksiyonun içinde izin verilir, dosya kapsamında ve bir yapıda izin verilmez). Gerçek bir derleme zamanı boyutu için #define N 10 ya da enum { N = 10 }; kullanın.
const char *p ne demek?
Sabit bir char'a gösterici demektir: p'nin nereyi gösterdiğini değiştirebilirsiniz, ama gösterdiği karakteri değiştiremezsiniz. char * const p bunun tersidir - değiştirilebilir bir char'a sabit bir gösterici. const char * const p ikisini de kilitler. Bildirimi isimden dışarı doğru okuyun.