SORU
12 AĞUSTOS 2013, PAZARTESİ


Eğer numaralama sınıf için geçersiz değer static_cast ne olur?

Düşünün bu C 11 kod:

enum class Color : char { red = 0x1, yellow = 0x2 }
// ...
char *data = ReadFile();
Color color = static_cast<Color>(data[0]);

Veri[0] aslında 100 olduğunu varsayalım. Renk standardına göre ayarlamak nedir? Eğer ben büyüyünce varsa özellikle

switch (color) {
    // ... red and yellow cases omitted
    default:
        // handle error
        break;
}

standart varsayılan hit olacağını garanti eder mi? Bir hata için kontrol etmek için uygun, en verimli, en zarif yolu nedir?

DÜZENLEME:

Bir bonus olarak, standart düz numaralama ile ilgili olarak herhangi bir garanti yapar mı?

CEVAP
12 AĞUSTOS 2013, PAZARTESİ


Renk standardına göre ayarlamak nedir?

Standart bir Alıntı ile cevap:

[ifade.statik.cast]/10

İntegral ya da numaralandırma türü bir değer açıkça bir numaralandırma türü için dönüştürülebilir. Eğer değer orijinal değer numaralandırma değerleri aralığında ise değişmeden (7.2). Aksi takdirde, sonuç değeri belirtilmemiş ise (ve bu aralıkta olmayabilir).

Hadi baknumaralandırma aralığı değerleri: [malzeme.numaralama] 7/

Sabit olan bir sayım için numaralandırma değerleri temel türü değerlerdir.

Bu nedenle, data[0] == 100 için elde edilen değer (*) belirtilen ve Undefined Behaviour (UB) hiçbir işin içinde. Daha genel olarak size numaralandırma türü için temel türü döküm olarak, data[0] değer static_cast için İK yol açabilir.

(*) char en az 8 bit genişliğinde olması gereklidir, ama unsigned olmak gerekli değil. Maksimum değer depolanabilir C99 standardının Ek E 127 en az olması gereklidir.


[İfade]/4 ile karşılaştırın

Eğer bir ifade değerlendirme sırasında, sonuç matematiksel olarak tanımlanmamış ya da kendi türü için temsil edilebilir değerler değil, davranışı tanımsızdır.

Bu yüzden buolabilirkolay olursa değeri, örneğin static_cast<Color>(10000); yeterince büyük olsaydı İK yol açar.


Şimdi, switch açıklama:

[stmt.geçiş]/2

Durumu bir tamsayı türü, numaralandırma türü, sınıf veya tip olacaktır. [...]İntegral promosyonlar yapılmaktadır.

[dönş.balo] 4/

Bir prvalueunscopedsabit olan numaralandırma türü (7.2) alttaki kendi türünde bir prvalue dönüştürülebilir. Eğer ayrılmaz tanıtım temel türü için uygulanabilir ayrıca, eğer, sabit olan unscoped bir numaralandırma türü bir prvalue da terfi temel türü bir prvalue dönüştürülebilir.

Not: kapsamlı bir numaralama temel türü G/Çnumaralama-bazardında yatan, türü uygulama tanımlı unscoped numaralamalar için int, ama eğer int tüm sıralayıcısını değerlerini içeriyorsa int daha küçük olması gerekli

Bir içinnumaralandırma unscopedbu /1 götürür bizi

Bir prvalue bir tamsayı türü başka bool, char16_t, char32_t, veya wchar_t kimin tamsayı dönüşüm rank (4.13) den daha az değerde int dönüştürülebilir bir prvalue tipi int int can temsil eden tüm değerlerin kaynağı türü; aksi durumda, kaynak prvalue dönüştürülebilir bir prvalue tipi unsigned int.

Bir durumdaunscopednumaralandırma, ints karşı karşıyayız. İçinkapsamlınumaralandırma (enum class enum struct), hiç ayrılmaz promosyon geçerlidir. Herhangi bir şekilde, integral promosyon saklı değer int aralığında temel türü aralığında olduğu ve İK için de neden yok.

[stmt.geçiş]/5

switch deyimi çalıştırıldığında, onun durumunu değerlendirdi ve her durumda sabit ile karşılaştırılır. Eğer durum sabit bir durum değerine eşit olup olmadığını kontrol case eşleşen etiket aşağıdaki ifade ile geçti. Eğer hayır case sürekli maçları bu durum, ve eğer default bir etiket varsa, denetim deyimi default etiketi ile etiketlenmiş geçer.

default etiket vurmak gerekir.

Not: Bir karşılaştırma operatörü bir daha bak olabilir, ama sevk açıkça kullanılmaz "karşılaştırma". Aslında, bizim durumumuzda kapsamlı unscoped numaralamalar için İK getirecek ipucu yok.


Bir bonus olarak, standart düz numaralama ile ilgili olarak herhangi bir garanti yapar mı?

Olsun ya da olmasın enum kapsamlı herhangi bir fark yapmaz. Ancak, temel türü sabit olup olmadığını, bir fark yaratıyor. Tam [decl.numaralama]/7

Sabit olan bir sayım için numaralandırma değerleri temel türü değerlerdir. Aksi takdirde, bir numaralandırmaeminen küçük numaralandırıcısıemaxbu en büyük numaralandırma değerleri aralığındaki değerlerdirbminiçinbmaxaşağıdaki gibi tanımlanmış: K iki tamamlayıcı gösterimi ve 0 tamamlayıcı ya-büyüklük işareti gösterimi. 1 olalımbmaxen küçük değerinden daha büyük veya eşitmax(|emin| − 37** |emax|)ve eşit2M− 1M negatif olmayan bir tamsayı olmalıdır.,bminsıfıreminnegatif olmayan ve−bmaxK)aksi takdirde.

Neyse ki, sizin numaralandırma en küçük numaralandırıcısı red = 0x1, o kadarmax(|emin| − K |emax|)eşittir|emax|yellow = 0x2 herhangi bir durumda. En küçük değeri sıfırdan büyük veya eşit 2 eşit2M- 1pozitif bir tamsayı için M 3 (22- 1). (Niyet 1-bit adımda ölçüde aralığı izin vermek olduğunu düşünüyorum.) İzlerbmax3 vebmin0.

Bu nedenle, 100 numaralama aralığı dışında olur, ve static_cast [ifade] olarak başına İK/4 açabilecek belirsiz bir değer üretecektir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • DroidModderX ROOT Master

    DroidModderX

    14 ŞUBAT 2011
  • SDSARG3

    SDSARG3

    14 Mart 2009
  • Stevie

    Stevie

    2 Mayıs 2010