Pertanyaan Mengapa gcc tidak memperingatkan ketika nilai enum atau int dilewatkan sebagai argumen fungsi yang bool?


Saya memiliki kode berikut:

typedef enum
{
    FOO,
    BAR,
    BAZ
} foo_t;

static void afunc(bool is_it_on)
{
    /* do the job */
}

int main(void)
{
    afunc(BAZ);
    return 0;
}

Menyusun kode ini tidak menghasilkan pesan peringatan apa pun, bahkan dengan -Wall -Wextra opsi yang diberikan kepada kompilator. Saya bahkan sudah mencoba -Wconversion pilihan, yang tidak berpengaruh karena bool dan enum tampaknya memiliki ukuran yang sama untuk g ++. (ukuran dari enum jenis tidak didefinisikan dalam spesifikasi sejauh yang saya tahu)

Saya telah menyisir manual gcc dan tidak menemukan apa pun tentang itu.

Pertanyaan:

  • Apakah ada cara untuk memaksa compiler untuk menghasilkan peringatan dalam kasus-kasus seperti ini?
  • Atau apakah itu casting implisit ini legal dengan spesifikasi c ++?

Compiler yang saya gunakan: gcc 4.1.2


Diedit

Kesimpulan:

Satu-satunya solusi yang layak untuk ini tampaknya mendefinisikan tipe baru untuk mewakili 0 atau 1, dan menggunakannya sebagai gantinya bool.

Kode akan seperti berikut, dan g ++ mengeluh tentang konversi jenis:

typedef enum
{
    FOO1,
    FOO2
} foo_t;

typedef enum
{
    MY_FALSE,
    MY_TRUE
} my_bool_t;

void foo(my_bool_t a)
{
}

int main(void)
{
     /* 
      * gcc generates an error.
      * error: cannot convert ‘foo_t’ to ‘my_bool_t’ 
      * for argument ‘1’ to ‘void foo(my_bool_t)’
      */
    foo(FOO1);
    return 0;
}

9
2018-05-05 17:32


asal


Jawaban:


Ya, konversi tersirat itu sangat sah.

C ++ 11 draft n3290, §4.12 Konversi boolean:

Nilai prakiraan aritmatika, enumerasi tak berlistrik, penunjuk, atau penunjuk ke jenis anggota dapat dikonversi menjadi a   prvalue tipe bool. Nilai nol, nilai penunjuk null, atau nilai penunjuk anggota null dikonversi menjadi false;   nilai lainnya dikonversi menjadi true. Prvalue tipe std :: nullptr_t dapat dikonversi menjadi nilai dari   ketik bool; nilai yang dihasilkan salah.

Peringatan tentang konversi ini (untuk jenis aritmatika) mungkin akan menyebabkan sejumlah besar peringatan di semua tempat, saya tidak berpikir itu akan dapat dikelola.

Di C ++ 11, Anda bisa menggunakannya enums scoped untuk mencegah konversi implisit:

Ini gagal dikompilasi karena tidak ada konversi dari Foo untuk bool:

enum class Foo { ONE };

void tryit(bool b) { }

int main()
{
    tryit(Foo::ONE);
}

10
2018-05-05 17:42