Soru “İnt mask = ~ 0;” ın amacı nedir?


Aşağıdaki kod satırını gördüm İşte C.

 int mask = ~0;

Değerini yazdım mask C ve C ++ Her zaman yazdırır -1.

Bu yüzden bazı sorularım var:

  • Neden değer atama ~0 göre maskelemek değişken?
  • Amacı nedir ~0?
  • Kullanabilir miyiz -1 yerine ~0?

44
2017-09-23 06:19


Menşei


~0 sadece eşittir -1 2'sinde tamamlayıcı - phuclv
@PaulFloyd: Bağlantılı kaynak, ağırlık kaldırmada kullanılabilecek kadar saf bir iştir. - 6502
İlgili: Tüm bitleri true değerine ayarlamak için -1 kullanımı güvenli midir? - Cody Gray♦
Bir maske için imzalı türün kullanılmasının bana kodunuzda korkunç şeyler olduğunu söyler. - Sopel
Olası kopya ~ Operatör ne yapar? - Dukeling


Cevaplar:


Geçerli mimari üzerinde tamsayıda kaç bit olduğunu bilmek zorunda kalmadan, bir tamsayıdaki tüm ikili bitleri 1 bit olarak ayarlamanın taşınabilir bir yoludur.


78
2017-09-23 06:22



-1 ayrıca tüm bitleri bir tamsayıda 1 genişliğini bilmeden 1'e ayarlar int yazın. Sadece iki tamamlayıcı kullanımını ima eder - phuclv
@ LưuVĩnhPhúc doğru. ~ 0 yönteminin daha az bağımlılığı vardır. İmzasız, iki-olmayanın iltifat sistemlerinde çalışır ve (muhtemelen) daha az şifrelidir. - Richard Hodges
@chqrlie neden olmasın? BTW, bit maskeleri için işaretli değerleri kullanarak garip bir fikirdir. - P__J__
@ PeterJ_01: Varsa long daha fazla bit var int, sonra ~0u (hangi türü vardır unsigned) olabilir sıfır uzatılmış başlatmanın bir parçası olarak u. - Henning Makholm
Bu, kullanıcının tamamlayıcısı üzerinde taşınabilir değildir: uygun bir derleyicinin karar verebileceği negatif bir sıfır verir, bu da bir tuzak temsilidir. Bu noktada UB var. Adil olmak gerekirse, böyle bir uygulama söylenemez var için all-olanlar değer int ilk sırada. - Kevin


C ve C ++, 3 farklı imzalı tamsayı formatına izin verir: işaret büyüklüğü, kişinin tamamlayıcısı ve iki tamamlayıcısı

~0 all-one bit üretecek işaret biçiminden bağımsız olarak Sistem kullanır. Bu nedenle bu daha taşınabilir göre -1

Ekleyebilirsiniz U sonek (ör. -1U) bir all-one bit kalıbı oluşturmak portably1. ancak ~0  niyetin daha net olduğunu belirtir: tüm bitleri 0 değerinde ters çevirirken -1 değeri eksi bir değere ihtiyaç olduğunu gösterir, ikili temsili değil

1 çünkü imzalanmamış işlemler her zaman Modulo azaltılmış, sonuç türüyle temsil edilebilecek en büyük değerden büyük olan sayıdır.


37
2017-09-23 06:23



Metin, 2'nin tamamlayıcısı 32 bitlik tamsayı kabul edilebileceğini söylüyor. - 6502


Bu 2'nin tamamlayıcı platformunda (varsayılır) -1 değerini verir, ancak -1 yazmayı doğrudan kurallarla yasaklar (sadece tamsayılar 0..255, unary !, ~ ve ikili &, ^, |, +, << ve >> izin verilir).


8
2017-09-23 06:30





Verilen görevleri gerçekleştirmek için operatörlere ve dil yapılarına bir dizi kısıtlama ile kodlama zorluğu üzerinde çalışıyorsunuz.

İlk sorun -1 değerini döndür kullanmadan - Şebeke.

İkili tamamlayıcı ile negatif sayıları temsil eden makinelerde, değer -1 ayarlanan tüm bitlerle temsil edilir 1, yani ~0 değerlendirir -1:

/* 
 * minusOne - return a value of -1 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 2
 *   Rating: 1
 */
int minusOne(void) {
  // ~0 = 111...111 = -1
  return ~0;
}

Dosyadaki diğer sorunlar her zaman doğru şekilde uygulanmaz. İkinci problem, gerçeği temsil eden bir boolean değerini döndürmektir. int değer 16 bit imzalanmış olacak short bir kusuru vardır:

/* 
 * fitsShort - return 1 if x can be represented as a 
 *   16-bit, two's complement integer.
 *   Examples: fitsShort(33000) = 0, fitsShort(-32768) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 1
 */
int fitsShort(int x) {
  /* 
   * after left shift 16 and right shift 16, the left 16 of x is 00000..00 or 111...1111
   * so after shift, if x remains the same, then it means that x can be represent as 16-bit
  */
  return !(((x << 16) >> 16) ^ x); 
}

Sola kayma değeri negatif olan bir değerin veya kayma değeri aralığının ötesindeki bir sayıdır. int tanımlanmamış bir davranışa sahiptir, doğru bir değere doğru kayması uygulama tanımlanmıştır, bu yüzden yukarıdaki çözüm yanlıştır (muhtemelen beklenen çözüm olsa da).


5
2017-09-23 13:49





Loooong önce, hafızayı 1K ZX 80 veya ZX 81 gibi son derece sınırlı ekipmanlara nasıl kaydettiniz. BASIC’de

Let X = NOT PI

ziyade

LET X = 0

Sayılar 4 baytlık kayan nokta olarak saklandığından, ikincisi NOT ve PI'nin her birinin bir tek bayt aldığı birinci NOT PI alternatifinden 2 bayt daha fazla alır.


2
2017-09-23 20:17



Tam olarak değil. Bu örneklerde, tüm (anahtar) kelimeler, eşittir işareti, değişken isimleri ve tek bayt olarak kodlanmıştır. gözle görülür sıfır kendisi. Bununla birlikte, sayısal sabitleri, yürütücü tarafından kullanıldı ancak kaynakta gösterilmeyen 4 baytlık kayan noktalı değerle (bir çıkış baytı?) Takip etti. Bu nedenle, burada boyut farkı 3 değil, hatta 4 bayttır. - CiaPan
Çalışmalıyım ... sadece bazı ZX Spectrum emülatöründe yaptım ve teybe / diske kaydettim. İlki 40 ve seond 35 bayt kullanır, dolayısıyla 5 baytlık bir fark. Eh, eğer ZX 81'de olduğu gibi sadece 1k'lık bir dosya varsa, sanırım bu dosya boyutunda yüzde yarım bir tasarruf ve bu yüzden kullanıldı ... OP sorusuna geri dönersek - bir bayt veya iki tasarruf edersiniz (veya 5) bugün x = -1 yerine x = ~ 0 ifadesini kullanarak? Belki uzun x = ~ 0 gibi bir dönüşüm kullanarak? - skaak
Gerçekten çalışmalıyım ... sadece birkaç basit yolla bu c denemeye çalıştım ama derlenmiş dosya -1, ~ 0 ve ~ (0x00) için aynı boyuttaydı ... Eminim ki bu işte bazı mimariler var. Bir bayt ya da öylesine tasarruf edin, ancak bu günlerde her ne pahasına olursa olsun kaçınılmalıdır. Derlenmiş dosyalar yaklaşık 8,5 bayt. Bu ZX81'e kalp krizi geçirir ... - skaak
Modern C derleyicileri tanıyacak kadar akıllıdır ~0 ve -1 aynı değerde. Ayrıca kodu maksimum hıza veya minimum boyuta göre de optimize edebilir, böylece derleme seçenekleri ile oynamak zorunda kalırsınız. Ayrıca, derlenmiş kod fonksiyonların giriş noktalarının daha iyi hizalanması için 4, 8 veya 16 bayta kadar yuvarlanabilir. obj dosya boyutu, sizin amaçlarınız için uygun değildir. Kodun bayt byte bayt temsilini görmek için C kodunu derlemek, hatta derlenmiş nesne modülünü (objdump gibi bir araçla) parçalara ayırmak isteyebilirsiniz. - CiaPan
Bu sistemlerde tamsayı tipi yok mu? Ve nasıl PI Tek bir bayt içinde saklanmalıdır? - phuclv


Tüm bilgisayar mimarileri arasında sayıları kodlamanın çeşitli yolları vardır. 2'nin tamamlayıcısı kullanıldığında, bu her zaman doğru olacaktır:~0 == -1. Öte yandan, bazı bilgisayarlar, yukarıdaki örneğin doğru olmayan negatif sayıları kodlamak için 1'in tamamlayıcısı kullanırlar; ~0 == -0. Evet, 1s tamamlayıcısı negatif sıfırdır ve bu yüzden çok sezgisel değildir.

Yani sorularına

  • Maske içindeki tüm bitlerin eşit olması için ~ 0 maskesine atanır. mask & sth == sth
  • ~ 0, kullanılan platforma bakılmaksızın tüm bitlerin 1'e eşit olması için kullanılır
  • Bilgisayar platformunuzun 2'nin tamamlayıcı sayı kodlamasını kullandığından eminseniz ~ 'yerine -1' yi kullanabilirsiniz.

Kişisel düşüncem - kodunuzu olabildiğince çok platformdan bağımsız hale getirin. Maliyet nispeten küçüktür ve kod başarısızlığa neden olur


0
2017-09-23 12:46



Yalnızca 1'ler tamamlayıcı uygulama negatif sıfırları destekliyorsa. Ayrıca bakınız bu cevap - JHBonarius