operator bool ++ dan -

104

Hari ini saat menulis beberapa kode Visual C ++ saya telah menemukan sesuatu yang mengejutkan saya. Tampaknya C ++ mendukung ++ (increment) untuk bool, tetapi tidak - (decrement). Apakah ini hanya keputusan acak, atau ada alasan di balik ini?

Ini mengkompilasi:

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

Ini tidak:

static HMODULE hMod = NULL;
static bool once = true;
if (once--)
    hMod = LoadLibrary("xxx");
Suma
sumber
2
hm, sama untuk kompiler xcode dan gcc
Vladimir
Ya, ++oncedan once++bekerja dengan gcc, tetapi bukan penurunannya.
Justin Ardini
Mungkin memberi tag ulang "riwayat" alih-alih "operator-kata kunci", jadi ini dikelompokkan dengan semua penjelasan menyenangkan lainnya tentang mengapa berbagai hal gila masuk akal jika Anda mempertimbangkan riwayat? :)
Jon Hanna
Perhatikan pada C ++ 17 operator pre-increment boolsudah tidak digunakan lagi, souce .
cogle
ini dapat diganti dengan std::exchange(once,false)(note: not atomic), jika Anda menginginkan sesuatu yang tidak usang.
golvok

Jawaban:

90

Itu berasal dari sejarah menggunakan nilai integer sebagai boolean.

Jika xadalah int, tetapi saya menggunakannya sebagai boolean karena if(x)...peningkatan itu berarti bahwa apa pun nilai kebenarannya sebelum operasi, itu akan memiliki nilai kebenarantrue setelahnya (kecuali overflow).

Namun, tidak mungkin untuk memprediksi hasil dari --pengetahuan yang diberikan hanya dari nilai kebenaran x, karena dapat menghasilkan false(jika nilai integral adalah 1) atau true(jika nilai integral adalah yang lain - terutama ini termasuk 0 [ false] dan 2 atau lebih [true ]).

Jadi sebagai tangan pendek ++bekerja, dan-- tidak.

++ diizinkan pada bools untuk kompatibilitas dengan ini, tetapi penggunaannya tidak digunakan lagi dalam standar.


Ini mengasumsikan bahwa saya hanya menggunakan xsebagai boolean, yang berarti bahwa overflow tidak dapat terjadi sampai saya melakukannya ++cukup sering untuk menyebabkan overflow itu sendiri. Bahkan dengan char sebagai tipe yang digunakan dan CHAR_BITSsesuatu yang rendah seperti 5, itu 32 kali sebelum ini tidak berfungsi lagi (itu masih cukup argumen karena itu adalah praktik yang buruk, saya tidak membela praktiknya, hanya menjelaskan mengapa itu berhasil) untuk 32-bit intkami tentu saja harus menggunakan ++2 ^ 32 kali sebelum ini menjadi masalah. Dengan --meskipun itu hanya akan menghasilkan falsejika saya mulai dengan nilai 1 untuk true, atau dimulai dengan 0 dan digunakan ++tepat sekali sebelumnya.

Ini berbeda jika kita mulai dengan nilai yang hanya sedikit di bawah 0. Memang, dalam kasus seperti ini kita mungkin ingin ++menghasilkan falsenilai pada akhirnya seperti:

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

Namun, contoh ini diperlakukan xsebagai di intmana - mana kecuali bersyarat, jadi itu setara dengan:

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

Yang berbeda hanya menggunakan xsebagai boolean.

Jon Hanna
sumber
1
Terima kasih. Senang mengetahui saya masih bisa memberikan jawaban orang-orang seperti ini, mengingat berapa lama sejak saya benar-benar menulis baris C ++ :)
Jon Hanna
8
Tetapi jika x adalah -1 (TRUE di beberapa platform seperti VB), ++ x akan menjadi FALSE.
James Curran
4
@ James, dalam C dan C ++ itu akan menjadi kasus yang saya pikirkan ketika saya berkata ("barring overflow"). Sebenarnya di VB setiap bukan nol memiliki nilai kebenaran TRUE (seperti di C), tetapi mereka memiliki -1 daripada 1 sebagai hasil dari operasi boolean yang benar karena TIDAK (TRUE) adalah FALSE, NOT (FALSE) adalah TRUE, x ATAU TRUE is TRUE, x OR FALSE adalah x, x AND FALSE is FALSE dan x AND TRUE adalah x, dsb. Menggunakan operator yang sama untuk operasi boolean dan bit-wise (karena VB mengasumsikan dua-komplemen jadi -1 semuanya 1 bit). Namun, ini dapat menyebabkan beberapa bug aneh di VB jika pembuat kode tidak menangkap bahwa 2 (benar) DAN 4 (benar) menghasilkan 0 (salah).
Jon Hanna
2
@ JonHanna: ANSI C89 adalah standar C pertama. Komite ANSI C menemukan <limits.h>header dan CHAR_BITmakro. Sebelum itu, saya kira secara teoritis mungkin ada implementasi di mana charlebih sempit dari 8 bit, tetapi sejauh yang saya tahu tidak ada. Secara khusus, K & R1 (diterbitkan pada tahun 1978) mencantumkan 4 contoh implementasi, yang semuanya memiliki 8-bit atau 9-bit char.
Keith Thompson
1
@JonHanna: Implementasi C yang sesuai harus dimiliki CHAR_BIT >= 8. Standar tidak membuat tunjangan untuk target yang sulit. (Anda dapat memiliki penerapan yang tidak sesuai, tentu saja.)
Keith Thompson
29

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

5.2.6-2

Operand dari postfix - diturunkan secara analog ke operator postfix ++, kecuali operannya tidak boleh berjenis bool. [Catatan: Untuk kenaikan dan penurunan prefiks, lihat 5.3.2. ]

Dan tidak mengherankan ...

5.3.2-2

Operand dari prefiks - dimodifikasi dengan mengurangi 1. Operand tidak boleh bertipe bool. Persyaratan pada operan prefiks - dan properti hasilnya sama dengan yang ada pada prefiks ++. [Catatan: Untuk kenaikan dan penurunan postfix, lihat 5.2.6. ]

Juga 5.6.2-1 dan 5.3.2-1 menyebutkan bahwa ++ untuk bools harus benar dan Lampiran D-1 menyatakan bahwa ++ pada bools sudah tidak digunakan lagi.

Mainframe Nordik
sumber
3
@BlueRaja: Lihat jawaban Jon Hanna.
Justin Ardini
9

Karena alasan sejarah, ini didukung. Tapi perhatikan bahwa ... Penggunaan operand tipe bool dengan operator ++ tidak digunakan lagi, lihat Bagian 5.3.2 di C ++ Standard (n3092)

5.3.2 Peningkatan dan penurunan [expr.pre.incr]

  • Operand prefiks ++ diubah dengan menambahkan 1, atau disetel ke true jika bool (penggunaan ini tidak digunakan lagi). Operand harus menjadi nilai l yang dapat dimodifikasi. Jenis operan harus berupa tipe aritmatika atau penunjuk ke tipe objek yang ditentukan secara lengkap. Hasilnya adalah operan yang diperbarui; ini adalah nilai l, dan ini adalah bidang bit jika operannya adalah bidang bit. Jika x bukan tipe bool, ekspresi ++ x setara dengan x + = 1 [Catatan: lihat diskusi tentang penjumlahan (5.7) dan operator penugasan (5.17) untuk informasi tentang konversi. —Kirim catatan]
  • Operand dari prefiks - dimodifikasi dengan mengurangi 1. Operand tidak boleh bertipe bool. Persyaratan pada operan prefiks - dan properti hasilnya sama dengan yang ada pada prefiks ++.
Abhay
sumber
3
  • Dengan standar lama (C ++ 98) ini bukan merupakan kesalahan.
  • Dengan standar baru yang menambah boolean sudah tidak digunakan lagi. (C ++ 11)
  • Anda dapat menggunakan incrementation pada boolean hingga C ++ 17.
mustafagonul
sumber