Menu

C'de Enum: Adlandırılmış Sabitler, Otomatik Numaralama ve Enum'dan Metne

C'de bir enum nasıl tanımlanır - otomatik numaralama, açık değerler, derleyicinin eksik durumları yakalaması için enum'ları switch içinde kullanmak, bir enum'u metne çevirmek ve onları okunaklı tutan adlandırma gelenekleri.

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

Çıplak sayılarla dolu kod, kimsenin okuyamadığı koddur. if (state == 2) size hiçbir şey söylemez; if (state == STATE_RUNNING) her şeyi söyler. Bir enum, C'nin küçük ve sabit bir tam sayı kümesine düzgün isimler verme yoludur - ve bir yığın #define'ın aksine, derleyicinin bildiği tek bir tip altında gruplanmış gelirler.

Bir Enum Tanımlamak

Bildirim bir etiket adlandırır ve numaralandırıcıları süslü parantez içinde listeler:

Hemen dikkat edilecek iki şey. Birincisi, numaralama 0'dan başlar ve birer birer artar, dolayısıyla RED 0, GREEN 1, BLUE 2'dir. İkincisi, numaralandırıcı isimleri çevreleyen kapsamın her yerinde görünürdür - Color.GREEN değil, GREEN yazarsınız. Değişkenlerinizle aynı isim alanında yaşarlar; C kodunun çakışmaları önlemek için geleneksel olarak onları BÜYÜK yazmasının ya da tiple öneklemesinin (COLOR_RED) sebebi budur.

Bir enum'u yazdırmak %d kullanır, çünkü bir numaralandırma değeri bir tam sayı değeridir.

Açık Değerler

Herhangi bir numaralandırıcıya açık bir sabit atayın, ondan sonrakiler oradan devam eder:

Değerlerin benzersiz ya da sıralı olması gerekmez - iki numaralandırıcı bir sayıyı paylaşabilir ki bu takma adlar için zaman zaman yararlıdır (COLOR_DEFAULT = COLOR_BLACK). Derleme zamanı tam sayı sabitleri olmalıdırlar, dolayısıyla birini bir değişkenden hesaplayamazsınız.

Yaygın bir deyim bunu sayıyı kaydetmek için kullanır:

enum Suit {
    CLUBS, DIAMONDS, HEARTS, SPADES,
    SUIT_COUNT           /* otomatik olarak 4 - yeni bir renk eklerseniz doğru kalır */
};

SUIT_COUNT gerçek bir renk değildir; onların sayısıdır ve otomatik numaralama tarafından bedavaya güncel tutulur. Döngüler ve dizi boyutları onu kullanabilir ve asla bayatlamaz.

typedef enum

Yapılarda olduğu gibi, C'de tam tip adı enum Color'dır ve bir typedef anahtar kelimeyi düşürür:

Numaralandırıcılar 0'dan başlayan sıradan tam sayılar olduğu için dizi indeksi görevi de görürler - dx[DIR_EAST] hiçbir dönüşüm olmadan çalışır. Sıfır tabanlı bir enum'un tek en yararlı özelliği budur.

switch İçinde Enum'lar

Bir enum'u bir switch ile eşleştirmek, tipin kendini ödemeye başladığı yerdir. -Wall ile derleyin ve derleyici bir durumu unuttuğunuzda size söyler.

Enum'a bir STATE_FAILED ekleyin, GCC uyarır: enumeration value 'STATE_FAILED' not handled in switch. O uyarı, C'nin bir bütünlük denetimine en yakın şeyidir ve bu switch'leri default: durumu olmadan yazmak için güçlü bir sebeptir - bir default uyarıyı susturur ve yeni durumların ele alınmadan geçmesine izin verir. Bunun yerine geri dönüşü, describe'ın yaptığı gibi switch'ten sonra koyun.

Bir Enum'u Metne Çevirmek

C çalışma zamanında hiç isim tutmaz; printf("%s", GREEN) çalışamaz, çünkü GREEN yalnızca 1'dir. İki kalıp bunu çözer.

Derleyicinin denetlediği switch sürümü:

Ve daha kısa ama denetimsiz olan arama tablosu sürümü - dizi ile enum birbirinden koparsa hiçbir şey uyarmaz:

Belirtilmiş dizi indeksleri ([RED] = "RED") en azından isimleri yuvalarına bağlı tutar, dolayısıyla enum'u yeniden sıralamak metinleri sessizce karıştıramaz. Sınır denetimi önemlidir, çünkü hiçbir şey çağıranın enum dışında bir değer geçirmesini engellemez - bkz. sonraki bölüm.

Enum'lar Su Geçirmez Değildir

Bir enum değişkeni altta bir tam sayıdır ve C aralığı denetlemez:

Numaralandırıcılar üzerinde aritmetik çalışır, düz int'lerle karşılaştırmalar çalışır ve aralık dışı bir dönüşüm kabul edilir. Dolayısıyla bir enum'a mükemmel bir belgeleme ve derleyici için iyi bir ipucu gözüyle bakın, bir garanti olarak değil. Programınızın dışından gelen - bir dosya, bir argüman, bir ağ mesajı - her değeri, üzerinde switch yapmadan önce doğrulayın.

Boyut ve Depolama

C17'de her numaralandırıcı bir int'e sığmalıdır - enum Huge { BIG = 3000000000 };, katı bir derleyicinin (-pedantic-errors) reddettiği bir kısıt ihlalidir; gcc ve clang varsayılan kipte bunu bir uzantı olarak kabul etse de. Numaralandırıcıların kendisi int tipindedir; enum tipinin boyutu ise gerçekleştirime bağlıdır (pratikte int):

(C23 bu kısıtı kaldırır: bir numaralandırıcı int aralığını aşabilir ve enum E : unsigned long { ... } ile alttaki tipi bile seçebilirsiniz. Araç zinciriniz C23'ü hedefleyene kadar numaralandırıcıları int içinde tutun.)

Kesin seçim gerçekleştirime bağlı olduğu için bir enum'u asla doğrudan ikili bir dosyaya ya da ağ paketine yazıp başka bir makinenin onu geri okumasını beklemeyin. Sınırda <stdint.h>'deki uint8_t ya da uint32_t gibi sabit genişlikli bir tipe dönüştürün.

Enum ile #define Karşılaştırması

İkisi de bir sayıya isim verir. Enum genellikle daha iyidir:

enum#define
İşleyenderleyiciön işlemci
Gruplamailişkili değerler bir tipi paylaşırher sabit bağımsızdır
Otomatik numaralamaevethayır, elle numaralarsınız
Hata ayıklayıcıda görünürçoğu zaman, isimlehayır, yalnızca sayı
switch bütünlük uyarısıevethayır
Kapsamblok kapsamına uyarmetinsel, #undef'e kadar

Sabit bir tam sayı olmadığında (bir metin, bir float) ya da koşullu derlemede olduğu gibi ön işlemcinin kendisi tarafından kullanılabilir olması gerektiğinde #define'a uzanın. İlişkili tam sayı durumları, bayraklar ya da türlerden oluşan bir küme için bir enum kullanın.

Adlandırma Gelenekleri

Enum'lar kolayca çakışır, çünkü isimleri sıradan kapsamda durur. Büyük C kod tabanlarını aklı başında tutan gelenekler:

  • Her numaralandırıcıyı tiple önekleyin: COLOR_RED, STATE_IDLE, HTTP_OK. Bir grafik programındaki öneksiz RED, eninde sonunda birinin başka bir RED'iyle karşılaşacaktır.
  • Numaralandırıcıları BÜYÜK_HARF yazın, diğer sabitlerin göründüğü gibi.
  • Tipi tekil PascalCase ya da snake_case_t olarak adlandırın: Color, State ya da color_t; proje boyunca tutarlı biçimde.
  • Enum ile döngü kuracak ya da indeksleyecekseniz sona bir _COUNT nöbetçisi ekleyin.

Sıkça Sorulan Sorular

C'de bir enum nasıl tanımlanır?

enum Color { RED, GREEN, BLUE };, değerleri bu üç adlandırılmış sabit olan bir tip tanımlar. Varsayılan olarak 0'dan numaralanırlar, dolayısıyla RED 0, GREEN 1 ve BLUE 2'dir. Bir değişkeni enum Color c = GREEN; ile bildirin ya da yalnızca Color c yazabilmek için bir typedef ekleyin.

C'de bir enum'a belirli değerler atanabilir mi?

Evet: enum Status { OK = 200, NOT_FOUND = 404, ERROR = 500 };. Bazılarını ayarlayıp diğerlerinin devam etmesine izin verebilirsiniz - açık değeri olmayan her isim bir öncekinden devam eder, dolayısıyla enum { A = 10, B, C }; B'yi 11, C'yi 12 yapar.

C'de bir enum metne nasıl çevrilir?

C'nin yerleşik bir yolu yoktur; numaralandırıcı isimleri çalışma zamanında var olmaz. Alışıldık yaklaşım, değer başına bir metin sabiti döndüren switch içeren küçük bir fonksiyon ya da enum ile indekslenen bir metin dizisidir. Switch sürümü daha güvenlidir, çünkü yeni bir numaralandırıcının case'i yoksa -Wall uyarır.

C'de bir enum'un boyutu nedir?

Gerçekleştirime bağlıdır, ama pratikte sizeof(int) - çoğu sistemde 4 bayt. Derleyici, her numaralandırıcıyı tutabilecek bir tam sayı tipi seçer. İkili bir dosya ya da ağ paketi düzenlerken belirli bir boyut varsaymayın; orada <stdint.h>'den sabit genişlikli bir tip kullanın.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA