Bayrak numaralandırmaları neden genellikle onaltılık değerlerle tanımlanır?


122

Çoğu zaman onaltılık değerler kullanan bayrak enum bildirimleri görüyorum. Örneğin:

[Flags]
public enum MyEnum
{
    None  = 0x0,
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4,
    Flag4 = 0x8,
    Flag5 = 0x10
}

Bir sıralama beyan ettiğimde, genellikle şu şekilde beyan ederim:

[Flags]
public enum MyEnum
{
    None  = 0,
    Flag1 = 1,
    Flag2 = 2,
    Flag3 = 4,
    Flag4 = 8,
    Flag5 = 16
}

Bazı insanların değeri ondalık yerine onaltılık olarak yazmayı seçmesinin bir nedeni veya mantığı var mı? Gördüğüm kadarıyla, onaltılık değerleri kullanırken kafanızın karışması ve Flag5 = 0x16bunun yerine yanlışlıkla yazmak daha kolay Flag5 = 0x10.


4
Daha az olasılıkla yazacağım bir şey yapmış Ne 10ziyade 0x10sen ondalık sayılar kullanılırsa? Özellikle bunlar uğraştığımız ikili sayılar olduğundan ve onaltılık önemsiz bir şekilde ikiliye / ikiliden dönüştürülebilir mi? 0x111birinin kafasından tercüme etmek 273...
— cHao

4
C # 'ın ikinin güçlerini yazmayı açıkça gerektirmeyen bir sözdizimine sahip olmaması utanç verici.
— Albay Panic

Burada saçma sapan bir şey yapıyorsun. Bayrakların ardındaki amaç, bitsel olarak birleştirilmeleridir. Ancak bitsel kombinasyonlar, türün öğeleri değildir. Değer Flag1 | Flag23'tür ve 3 herhangi bir alan değerine karşılık gelmez MyEnum.
— Kaz

Onu nerede göruyorsun? reflektörlü?
— giammin

@giammin Bu genel bir sorudur, belirli bir uygulama hakkında değil. Örneğin, açık kaynaklı projeleri veya sadece internette bulunan kodu alabilirsiniz.
— Adi Lester

Yanıtlar:


184

Gerekçeler farklı olabilir, ancak gördüğüm bir avantaj, onaltılı tabanın size şunu hatırlatmasıdır: "Tamam, artık rastgele insan icat edilmiş on üssünde sayılarla uğraşmıyoruz. Bitlerle uğraşıyoruz - makinenin dünyası - ve biz kurallarına göre oynayacağız. " Onaltılık, verilerin bellek düzeninin önemli olduğu nispeten düşük seviyeli konularla uğraşmadığınız sürece nadiren kullanılır. Bunu kullanmak, şu anda içinde bulunduğumuz durumun bu olduğu gerçeğine işaret ediyor.

Ayrıca, C # konusunda emin değilim, ancak C'nin x << ygeçerli bir derleme zamanı sabiti olduğunu biliyorum . Bit kaydırma kullanmak en net olanıdır:

[Flags]
public enum MyEnum
{
    None  = 0,
    Flag1 = 1 << 0,
    Flag2 = 1 << 1,
    Flag3 = 1 << 2,
    Flag4 = 1 << 3,
    Flag5 = 1 << 4
}

7
Bu çok ilginç ve aslında geçerli bir C # numaralandırması.
— Adi Lester

13
Bu gösterimle +1, sıralama değeri hesaplamalarında asla hata yapmazsınız
— Sergey Berezovskiy

1
@AllonGuralnek: Derleyici [Flags] ek açıklamasına göre benzersiz bit konumları atıyor mu? Genellikle 0'dan başlar ve 1'lik artışlarla gider, bu nedenle 3 (ondalık) atanan herhangi bir enum değeri ikili olarak 11 olur ve iki biti ayarlar.
— Eric J.

2
@Eric: Huh, neden bilmiyorum ama ikisinin güç değerlerini atadığından her zaman emindim. Az önce kontrol ettim ve sanırım yanılmışım.
— Allon Guralnek

38
x << yGösterimle bir başka eğlenceli gerçek . 1 << 10 = KB, 1 << 20 = MB, 1 << 30 = GBVe bu kadar. Gidebileceğiniz bir arabellek için 16 KB'lik bir dizi yapmak istiyorsanız gerçekten çok güzelvar buffer = new byte[16 << 10];
— Scott Chamberlain

43

Bunların ikili bayraklar olduğunu görmeyi kolaylaştırır .

None  = 0x0,  // == 00000
Flag1 = 0x1,  // == 00001
Flag2 = 0x2,  // == 00010
Flag3 = 0x4,  // == 00100
Flag4 = 0x8,  // == 01000
Flag5 = 0x10  // == 10000

Gerçi ilerleme bile net yapar:

Flag6 = 0x20  // == 00100000
Flag7 = 0x40  // == 01000000
Flag8 = 0x80  // == 10000000

3
Aslında 0x1, 0x2, 0x4, 0x8'in önüne 0 ekliyorum ... Bu yüzden 0x01, 0x02, 0x04, 0x08 ve 0x10 alıyorum ... Bunu okumayı daha kolay buluyorum. Bir şeyi mahvediyor muyum?
— LightStriker

4
@Light - Hiç de değil. Çok yaygındır, bu yüzden bunların nasıl hizalandığını görebilirsiniz. Sadece bitleri daha belirgin hale getirir :)
— Oded

2
@LightStriker , hex kullanmıyorsanız , onu oraya atacak . Yalnızca sıfır ile başlayan değerler sekizlik olarak yorumlanır. Yani 012aslında 10.
— Jonathon Reinhart

@JonathonRainhart: Biliyorum. Ama bitfields kullanırken her zaman hex kullanırım. Bunun intyerine kendimi güvende hissedeceğimi sanmıyorum . Aptalca olduğunu biliyorum ... ama alışkanlıklar zor ölür.
— LightStriker

36

Ben dizisi hep 1,2,4,8 ve daha sonra bir 0'a eklemek sırf bu olduğunu düşünüyorum
Gördüğünüz gibi:

0x1 = 1 
0x2 = 2
0x4 = 4
0x8 = 8
0x10 = 16
0x20 = 32
0x40 = 64
0x80 = 128
0x100 = 256
0x200 = 512
0x400 = 1024
0x800 = 2048

1-2-4-8 dizisini hatırladığınız sürece, 2'nin güçlerini hatırlamak zorunda kalmadan sonraki tüm bayrakları oluşturabilirsiniz.


13

Çünkü [Flags]numaralamanın gerçekten bir bit alanı olduğu anlamına gelir . İle bayrakları birleştirmek için [Flags]bitsel AND ( &) ve OR ( |) operatörlerini kullanabilirsiniz. Bunun gibi ikili değerlerle uğraşırken, onaltılık değerlerin kullanılması neredeyse her zaman daha açıktır. İlk etapta onaltılı kullanmamızın nedeni budur . Her bir onaltılık karakter tam olarak bir yarım bayta (dört bit) karşılık gelir . Ondalık ile bu 1'den 4'e eşleme doğru değildir.


2
Bitsel işlemleri kullanma yeteneğinin, bayrak niteliği ile hiçbir ilgisi yoktur.
— Mattias Nordqvist

4

Çünkü hex'de ikinin gücünü ikiye katlamanın mekanik ve basit bir yolu var. Ondalık olarak bu zordur. Kafanızda uzun bir çarpma gerektirir. Onaltılık olarak basit bir değişikliktir. Bunu 1UL << 63ondalık olarak yapamayacağınız kadar yapabilirsiniz.


1
Bunun en mantıklı olduğunu düşünüyorum. Büyük bir değer kümesine sahip numaralandırmalar için en kolay yoldur (@ Hypercube örneğinin olası istisnası dışında).
— Adi Lester

3

Çünkü bitlerin bayrakta olduğu insanlar için takip etmek daha kolay. Her onaltılık rakam 4 bitlik bir ikiliye sığabilir.

0x0 = 0000
0x1 = 0001
0x2 = 0010
0x3 = 0011

... and so on

0xF = 1111

Tipik olarak bayraklarınızın bitlerle örtüşmemesini istersiniz, bunu yapmanın ve görselleştirmenin en kolay yolu, bayraklarınızı bildirmek için onaltılık değerler kullanmaktır.

Dolayısıyla, 16 bitlik bayraklara ihtiyacınız varsa, 4 basamaklı onaltılık değerler kullanacaksınız ve bu şekilde hatalı değerlerden kaçınabilirsiniz:

0x0001 //= 1 = 000000000000 0001
0x0002 //= 2 = 000000000000 0010
0x0004 //= 4 = 000000000000 0100
0x0008 //= 8 = 000000000000 1000
...
0x0010 //= 16 = 0000 0000 0001 0000
0x0020 //= 32 = 0000 0000 0010 0000
...
0x8000 //= 32768 = 1000 0000 0000 0000

Bu açıklama iyidir .... Eksik olan tek şey bitlerin,
— atlamaların
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.