bool operatörü ++ ve -


104

Bugün bazı Visual C ++ kodlarını yazarken beni şaşırtan bir şeyle karşılaştım. Görünüşe göre C ++, bool için ++ (artış) 'ı destekliyor ancak - (azaltma)' yı desteklemiyor. Bu sadece rastgele bir karar mı yoksa bunun arkasında bir sebep mi var?

Bu derler:

static HMODULE hMod = NULL;
static bool once = false;
if (!once++)
    hMod = LoadLibrary("xxx");

Bu değil:

static HMODULE hMod = NULL;
static bool once = true;
if (once--)
    hMod = LoadLibrary("xxx");

2
hm, xcode ve gcc derleyicisi için aynı
Vladimir

Evet ++onceve once++gcc ile çalışın, ancak azaltmalarla değil.
Justin Ardini

Belki "operatör-anahtar kelime" yerine "geçmişi" yeniden etiketleyin, bu nedenle bu, geçmişi göz önünde bulundurursanız, çeşitli çılgın şeylerin neden makul olduğuna dair diğer tüm eğlenceli açıklamalarla gruplandırılır? :)
Jon Hanna

C ++ 17 için önceden arttırma operatörü olarak Not boolkaldırıldı, sosu .
cogle

Kullanımdan kaldırılmamış bir şey istiyorsanız, bu std::exchange(once,false)(not: atomik değil ) ile değiştirilebilir .
golvok

Yanıtlar:


90

Tamsayı değerlerini boole olarak kullanma geçmişinden gelir.

Eğer bir xise int, ancak bunu bir boole olarak kullanıyorum, o if(x)...zaman artırma, işlemden önceki doğruluk değeri ne olursa olsun, ondan truesonra bir doğruluk değerine sahip olacağı anlamına gelecektir (taşma hariç).

Ancak, sonucunu tahmin etmek imkansız --, sadece gerçeği değerinin verilen bilginin xo yol açabilir olarak, false(integral değeri 1 ise) veya true(entegral değer başka bir şey ise - özellikle bu içermektedir 0 [ false] ve 2 ya da daha [ true]).

Yani kısa bir el ++çalıştı ve --çalışmadı.

++ bununla uyumluluk için bool'larda izin verilir, ancak kullanımı standartta kullanımdan kaldırılmıştır.


Bu, yalnızcax bir boole olarak kullandığımı varsayar , yani ++kendi başına bir taşmaya neden olacak kadar sık yapana kadar taşma gerçekleşemez. Kullanılan tür olarak char ve CHAR_BITS5 gibi düşük bir şey olsa bile , bunun işe yaramaması için 32 kat önce (bu hala kötü bir uygulama olması için yeterli bir argüman, uygulamayı savunmuyorum, sadece neden işe yaradığını açıklıyorum) 32 bit intiçin, ++bu bir sorun haline gelmeden önce elbette 2 ^ 32 kez kullanmamız gerekir . Bununla --birlikte, yalnızca false1 değeriyle başlasam trueveya 0 ile başlasam ve ++daha önce tam olarak bir kez kullanılırsam sonuçlanacaktır .

Bu, 0'ın sadece birkaç altında bir değerle başlarsak farklıdır. Aslında, böyle bir durumda ++, falsesonuçta aşağıdaki gibi bir değerle sonuçlanmak isteyebiliriz :

int x = -5;
while(++x)
  doSomething(x);

Bununla birlikte, bu örnek , koşullu hariç her yerde kabul xedilir int, dolayısıyla şuna eşdeğerdir:

int x = -5;
while(++x != 0)
  doSomething(x);

Yalnızca xboole olarak kullanmaktan farklı olan .


1
Teşekkür ederim. Gerçekten bir satır C ++ yazdığımdan beri ne kadar uzun olduğu göz önüne alındığında, hala bu konuda insanlara benzer cevaplar verebileceğimi bilmek harika :)
Jon Hanna

8
Ancak x -1 olsaydı (VB gibi bazı platformlarda DOĞRU), ++ x YANLIŞ olurdu.
James Curran

4
@James, C ve C ++ 'da bu, ("taşma engellenmesi") dediğimde düşündüğüm durum olurdu. Aslında VB'de sıfır olmayan herhangi bir DOĞRU değerine sahiptir (C'deki gibi), ancak gerçek boole işlemlerinin sonucu olarak 1 yerine -1'e sahiptir, çünkü o zaman NOT (DOĞRU) YANLIŞ, DEĞİL (YANLIŞ) DOĞRU, x VEYA DOĞRU DOĞRU, x VEYA YANLIŞ, x, x VE YANLIŞ YANLIŞ ve x VE DOĞRU, x, vb. Boole ve bit-bazlı işlemler için aynı işleçleri kullanır (çünkü VB iki-tamamlayıcı varsaydığı için -1'in tümü 1 bittir). Bununla birlikte, kodlayıcı 2 (doğru) VE 4 (doğru) sonucunun 0 (yanlış) ile sonuçlandığını yakalamıyorsa, bu VB'de bazı garip hatalara neden olabilir.
Jon Hanna

2
@JonHanna: ANSI C89 ilk C standardıydı. ANSI C komitesi <limits.h>başlık ve CHAR_BITmakroyu icat etti . Bundan önce, teorik olarak char8 bitten daha dar uygulamalar olabilirdi , ama bildiğim kadarıyla hiçbiri yoktu. Özellikle, K & R1 (1978'de yayınlandı) tümü 8 bit veya 9 bit olan 4 örnek uygulamayı listeler char.
Keith Thompson

1
@JonHanna: Bir uyumlu C uygulaması gerekir var CHAR_BIT >= 8. Standart, zor olan hedefler için izin vermez. (Elbette, uygun olmayan bir uygulamaya sahip olabilirsiniz.)
Keith Thompson

29

ANSI ISO IEC 14882 2003 (c ++ 03):

5.2.6-2

Postfix - işleneni, işlenenin bool türünde olmaması dışında, postfix ++ operatörüne benzer şekilde azaltılır. [Not: Önek artışı ve azaltması için bkz. 5.3.2. ]

Ve şaşırtıcı olmayan bir şekilde ...

5.3.2-2

Önek işleneni - 1 çıkarılarak değiştirilir. İşlenen bool türünde olmayacaktır. Önek işleneni ile ilgili gereksinimler - ve sonucunun özellikleri aksi takdirde önek ++ ile aynıdır. [Not: Sonek artışı ve azaltması için bkz. 5.2.6. ]

Ayrıca 5.6.2-1 ve 5.3.2-1, ++ for bools'un doğru olacağını belirtir ve Ek D-1, ++ on bools in kullanımdan kaldırıldığını belirtir.


3
@BlueRaja: Jon Hanna'nın cevabına bakın.
Justin Ardini

9

Tarihsel nedenlerden dolayı bu desteklenmiştir. Ancak şunu unutmayın ... ++ operatörü ile bool tipinde bir işlenenin kullanımı artık önerilmemiştir, C ++ Standardında (n3092) Bölüm 5.3.2'ye bakınız.

5.3.2 Arttırma ve eksiltme [expr.pre.incr]

  • Önek ++ işleneni 1 eklenerek değiştirilir veya bool ise true olarak ayarlanır (bu kullanım artık kaldırılmıştır). İşlenen, değiştirilebilir bir değer olacaktır. İşlenenin türü, aritmetik bir tür veya tamamen tanımlanmış bir nesne türüne bir gösterici olacaktır. Sonuç, güncellenmiş işlenen; bu bir ldeğerdir ve işlenen bir bit alanıysa bir bit alanıdır. X, bool türünde değilse, ++ x ifadesi x + = 1'e eşdeğerdir [Not: dönüştürmeler hakkında bilgi için toplama (5.7) ve atama operatörleri (5.17) tartışmalarına bakın. - notu gönder]
  • Önek işleneni - 1 çıkarılarak değiştirilir. İşlenen bool türünde olmayacaktır. Önek işleneni ile ilgili gereksinimler - ve sonucunun özellikleri aksi takdirde önek ++ ile aynıdır.

3
  • Eski standartlarda (C ++ 98) bu bir hata değildir.
  • Yeni standartların artırılmasıyla bir boole değeri kullanımdan kaldırılmıştır. (C ++ 11)
  • C ++ 17'ye kadar bir boolean üzerinde artış kullanabilirsiniz.
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.