Menu

C'de switch Deyimi: case'ler, break ve Alta Düşme

C switch deyiminin bir sabit listesinden nasıl tek bir dal seçtiği - case etiketleri, break neden önemli, kasıtlı ve kazara alta düşme, default, char ve enum üzerinde switch ve switch'in bir else-if zincirini ne zaman yendiği.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Tek Değer, Çok Sabit

Aynı değişkeni sabitlerle karşılaştırıp duran bir else if zinciri, C'de kendi deyimi olan bir kalıptır:

if (choice == 1)      { /* ... */ }
else if (choice == 2) { /* ... */ }
else if (choice == 3) { /* ... */ }
else                  { /* ... */ }

switch bunu daha doğrudan söyler. İfadeyi bir kez değerlendirir, sonra doğrudan eşleşen etikete atlar.

choice'u değiştirip tekrar çalıştırın. Yapı, geçerli değerler kümesini bir bakışta görünür kılar ki burada onu tercih etmenin asıl sebebi budur.

Söz Dizimi ve case Etiketlerindeki Kurallar

switch (tamSayiIfadesi) {
    case SABIT_1:
        deyimler
        break;
    case SABIT_2:
        deyimler
        break;
    default:
        deyimler
        break;
}

C'nin uyguladığı dört kısıt:

  • switch ifadesinin tam sayı tipi olmalıdır - int, char, short, long ya da bir enum. float değil, double değil ve metin değil.
  • Her case etiketi, derleme zamanında bilinen bir sabit ifade olmalıdır. n'in değişken olduğu case n: bir hatadır; case 3 + 4: ve case MAX: (bir #define ya da enum sabiti) sorunsuzdur.
  • İki case aynı değere sahip olamaz. Yinelenenler bir derleme hatasıdır ki bu küçük ama gerçek bir güvenlik ağıdır.
  • Bir case bir aralık ifade edemez. case 1 ... 5: standart C değil, bir GCC uzantısıdır; aralıklar için bir if kullanın.

default isteğe bağlıdır ve blokta herhangi bir yerde görünebilir, ama onu sona koymak neredeyse evrensel gelenektir. default olmadan eşleşmeyen bir değer yalnızca tüm switch'i atlar.

break: Neden İsteğe Bağlı Değil

C'de switch ile ilgili tek en şaşırtıcı şey, case etiketlerinin kutular değil atlama hedefleri olmasıdır. Yürütme bir etikete indiğinde, bir break'e ya da kapanış parantezine ulaşana dek - diğer case etiketlerinin üzerinden geçerek - altındaki her deyimden geçmeye devam eder.

İlk switch bir, iki ve uc yazdırır - case 1 ile eşleşti ve sonra ondan sonraki her şeyi çalıştırdı. İkincisi yalnızca bir yazdırır. O davranışa alta düşme denir ve bir break'i unutmak klasik C switch hatasıdır: program derlenmemek yerine sessizce yanlıştır.

gcc -Wall -Wextra -Wimplicit-fallthrough ile derleyin, derleyici bir sonrakine düşen her case'i gösterir.

Son case'teki break teknik olarak gereksizdir - blok zaten orada biter. Yine de yazın, böylece sonradan altına yeni bir case eklemek sessizce bir alta düşme yaratmaz.

Kasıtlı Alta Düşme

Alta düşme, kasıtlı olduğunda bir özelliktir. Aralarında deyim olmadan etiketleri üst üste dizmek, "bu değerler aynı şeyi yapar" demenin sıradan yoludur:

Üç etiket tek bir gövdeyi paylaşır; yinelenen kod yok ve uzun bir || koşulu yok. Derleyiciler bu biçim için uyarmaz, çünkü alta düşülecek deyim yoktur.

Aralarında deyim olan alta düşme - case 1'in çalışıp sonra kasıtlı olarak case 2'ye devam etmesi - daha nadirdir ve açık bir yorumu hak eder, çünkü okuyana eksik break'in bir karar olduğunun söylenmesi gerekir:

switch (level) {
    case 3:
        printf("ayrintili\n");
        /* fall through */
    case 2:
        printf("bilgi\n");
        /* fall through */
    case 1:
        printf("hatalar\n");
        break;
}

/* fall through */, GCC'nin uyarısının tanıdığı yorumdur, dolayısıyla tanı mesajını da susturur.

Karakterler Üzerinde switch

char bir tam sayı tipi olduğu için karakter sınıflandırması doğal bir uyumdur:

case 'a':'nın tek tırnak kullandığına dikkat edin - o karakterin tam sayı değerinden ibaret bir karakter sabiti. case "a": bir metin olurdu ve derlenmezdi.

Enum'lar Üzerinde switch

C'deki en iyi eşleşme, switch ile bir enum'dur. Case etiketleri okunaklı isimler olur ve derleyiciler switch her numaralandırıcıyı ele almadığında uyarabilir:

Burada kopyalamaya değer iki şey var. Her case return yapar, dolayısıyla break gerekmez - bir return fonksiyondan tamamen çıkar ki bu switch'i de bitirir. Ve default yoktur: -Wswitch ile (-Wall içinde bulunur), default'u dışarıda bırakmak, birinin beşinci bir durum ekleyip bu fonksiyonu unuttuğu gün derleyicinin uyarmasını sağlar. Bir default bunu gizlerdi.

Bir switch İçinde Değişken Bildirmek

Bir switch gövdesi tek bir bloktur, dolayısıyla bir case'teki bildirim ondan sonrakilerde görünürdür - ille de ilk değeri verilmiş olmasa da. Bir ilk değerin üzerinden atlamak C'de bir hatadır:

switch (n) {
    case 1:
        int x = 10;        // C'de hata: bir etiket bir bildirimin önüne böyle gelemez
        printf("%d\n", x);
        break;
    case 2:
        printf("%d\n", x); // x burada var, ama hiç ilk değer almadı
        break;
}

Bir case'in yerel değişkenlere ihtiyacı olduğunda onu kendi süslü parantezlerine sarın:

switch (n) {
    case 1: {
        int x = 10;
        printf("%d\n", x);
        break;
    }
    case 2:
        printf("iki\n");
        break;
}

switch mi if-else mi?

Şunların hepsi doğruysa switch'e uzanın: tek bir ifadeyi test ediyorsunuz, tam sayı tipinde ve onu sabit sabitlerle karşılaştırıyorsunuz. Menü işleme, enum durum makineleri, karakter sınıflandırması ve komut dağıtımı klasik durumlardır. Kazanç, okunabilirlik, yinelenen değer denetimi ve ele alınmamış numaralandırıcılar hakkında uyarabilen bir derleyicidir.

Testler aralıkları (score >= 90), kayan noktalı değerleri, metinleri (strcmp gerekir), birkaç farklı değişkeni ya da && ve || ile birleştirilmiş koşulları içerdiğinde if-else'e uzanın. Bunların hiçbiri bir case etiketi olarak ifade edilemez.

Başarım nadiren belirleyici etmendir. Derleyiciler yoğun bir switch'i bir atlama tablosuna, seyrek olanı karşılaştırmalara dönüştürür, dolayısıyla bir avuç case'te iki biçim ayırt edilemez. Niyeti ifade edeni seçin.

Sıkça Sorulan Sorular

C'de switch deyimi nasıl çalışır?

switch (ifade), bir tam sayı ifadesini bir kez değerlendirir, sabiti eşleşen case etiketine atlar ve oradan bir break'e ya da switch'in sonuna ulaşana dek çalışır. Hiçbir şey eşleşmezse, varsa default'a atlar; yoksa tüm bloğu atlar.

C switch'inde neden break gerekir?

Çünkü case etiketleri ayrı bloklar değil, atlama hedefleridir. break olmadan yürütme doğrudan sonraki case'in deyimlerine devam eder - buna alta düşme denir. Eksik bir break, C'deki en yaygın switch hatasıdır ve gcc -Wimplicit-fallthrough bunu işaretler.

C'de bir metin üzerinde switch yapılabilir mi?

Hayır. Bir C switch'i tam sayı ifadesi ister, dolayısıyla int, char ve enum değerleri çalışır, ama metinler, float'lar ve aralıklar çalışmaz. Bir metne göre dallanmak için bir if-else zincirinde strcmp kullanın ya da metni önce bir enum'a eşleyip onun üzerinde switch yapın.

C'de if-else yerine ne zaman switch kullanmalıyım?

Tek bir tam sayı ya da karakteri sabit bir sabitler listesiyle karşılaştırırken switch kullanın - menü komutları, enum durumları, karakter sınıflandırması. Testler aralıkları, birden fazla değişkeni ya da derleme zamanı sabitine eşitlik dışında bir şeyi içeriyorsa bir if-else zinciri kullanın.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA