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
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.
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
, veyawchar_t
kimin tamsayı dönüşüm rank (4.13) den daha az değerdeint
dönüştürülebilir bir prvalue tipiint
int
can temsil eden tüm değerlerin kaynağı türü; aksi durumda, kaynak prvalue dönüştürülebilir bir prvalue tipiunsigned int
.
Bir durumdaunscopednumaralandırma, int
s 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ı kontrolcase
eşleşen etiket aşağıdaki ifade ile geçti. Eğer hayırcase
sürekli maçları bu durum, ve eğerdefault
bir etiket varsa, denetim deyimidefault
etiketi ile etiketlenmiş geçer.
default
etiket vurmak gerekir.
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ırmae
min en küçük numaralandırıcısıemax bu en büyük numaralandırma değerleri aralığındaki değerlerdirbmin içinbmax aşağıdaki gibi tanımlanmış:K
iki tamamlayıcı gösterimi ve0
tamamlayıcı ya-büyüklük işareti gösterimi.1
olalımbmax en küçük değerinden daha büyük veya eşitmax(|emin| − 37** |e ve eşit2M− 1max|) M
negatif olmayan bir tamsayı olmalıdır.,bmin sıfıremin negatif olmayan ve−bmax aksi takdirde.K
)
Neyse ki, sizin numaralandırma en küçük numaralandırıcısı red = 0x1
, o kadarmax(|eK
|eyellow = 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.) İzlerb3
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.
Eğer işaretsiz bir değişken için negat...
Hızlı eğer bir tam sayı iki tamsayı (d...
() süper yükseltir "eğer data: tü...
Nasıl eğer değer boş ise Jackson bir a...
::push_back vector) kullanır değeri, s...