Apakah C ++ enum ditandatangani atau tidak? Dan dengan ekstensi, apakah aman untuk memvalidasi input dengan memeriksa bahwa itu adalah <= nilai maks Anda, dan meninggalkan> = nilai min Anda (dengan asumsi Anda mulai dari 0 dan bertambah 1)?
107
Jawaban:
Anda tidak boleh mengandalkan representasi khusus apa pun. Baca link berikut . Juga, standar mengatakan bahwa itu adalah implementasi-didefinisikan tipe integral mana yang digunakan sebagai tipe dasar untuk enum, kecuali bahwa itu tidak boleh lebih besar dari int, kecuali beberapa nilai tidak dapat masuk ke dalam int atau int unsigned.
Singkatnya: Anda tidak dapat mengandalkan enum yang ditandatangani atau tidak.
sumber
Mari kita pergi ke sumbernya. Inilah yang dikatakan dokumen standar C ++ 03 (ISO / IEC 14882: 2003) di 7.2-5 (Deklarasi pencacahan):
Singkatnya, kompilator Anda dapat memilih (jelas, jika Anda memiliki angka negatif untuk beberapa nilai ennumerasi Anda, itu akan ditandatangani).
sumber
Anda tidak harus bergantung pada mereka yang ditandatangani atau tidak. Jika Anda ingin membuatnya ditandatangani atau tidak ditandatangani secara eksplisit, Anda dapat menggunakan yang berikut ini:
sumber
Anda tidak boleh mengandalkannya baik ditandatangani atau tidak ditandatangani. Menurut standar itu adalah implementasi yang ditentukan tipe integral mana yang digunakan sebagai tipe dasar untuk enum. Dalam kebanyakan implementasi, ini adalah integer bertanda.
Dalam C ++ 0x enumerasi yang diketik dengan kuat akan ditambahkan yang memungkinkan Anda untuk menentukan jenis enumerasi seperti:
Meskipun sekarang, beberapa validasi sederhana dapat dicapai dengan menggunakan enum sebagai variabel atau tipe parameter seperti ini:
sumber
Kompilator dapat memutuskan apakah enum ditandatangani atau tidak.
Metode lain untuk memvalidasi enum adalah dengan menggunakan enum itu sendiri sebagai tipe variabel. Sebagai contoh:
sumber
Bahkan beberapa jawaban lama mendapat 44 suara positif, saya cenderung tidak setuju dengan semuanya. Singkatnya, saya tidak berpikir kita harus peduli
underlying type
dengan enum.Pertama, tipe Enum C ++ 03 adalah tipe tersendiri yang tidak memiliki konsep tanda. Sejak dari standar C ++ 03
dcl.enum
Jadi ketika kita berbicara tentang tanda jenis enum, katakanlah ketika membandingkan 2 operan enum menggunakan
<
operator, kita sebenarnya berbicara tentang secara implisit mengubah jenis enum menjadi beberapa jenis integral. Tanda dari tipe integral inilah yang penting . Dan saat mengonversi enum ke tipe integral, pernyataan ini berlaku:Dan, tampaknya, jenis enum yang mendasari tidak ada hubungannya dengan Promosi Integral. Karena standar mendefinisikan Promosi Integral seperti ini:
Jadi, apakah jenis enum menjadi
signed int
atauunsigned int
bergantung pada apakahsigned int
dapat berisi semua nilai enumerator yang ditentukan, bukan jenis enum yang mendasari.Lihat pertanyaan terkait saya Tanda Jenis Enum C ++ Salah Setelah Mengonversi ke Jenis Integral
sumber
-Wsign-conversion
. Kami menggunakannya untuk membantu menangkap kesalahan yang tidak diinginkan dalam kode kami. Tetapi +1 untuk mengutip standar, dan menunjukkan bahwa enum tidak memiliki jenis (signed
versusunsigned
) yang terkait dengannya.Di masa mendatang, dengan C ++ 0x, enumerasi yang diketik dengan kuat akan tersedia dan memiliki beberapa keuntungan (seperti keamanan tipe, tipe dasar eksplisit, atau cakupan eksplisit). Dengan itu Anda bisa lebih yakin tentang tanda jenisnya.
sumber
Selain apa yang telah dikatakan orang lain tentang ditandatangani / tidak ditandatangani, inilah yang dikatakan standar tentang kisaran jenis yang disebutkan:
7.2 (6): "Untuk pencacahan di mana e (min) adalah pencacah terkecil dan e (maks) adalah yang terbesar, nilai pencacahan adalah nilai-nilai jenis yang mendasari dalam rentang b (min) hingga b (maks ), di mana b (min) dan b (max) adalah, masing-masing, nilai terkecil dan terbesar dari bitfield terkecil yang dapat menyimpan e (min) dan e (max). Dimungkinkan untuk menentukan enumerasi yang memiliki nilai tidak ditentukan oleh salah satu enumeratornya. "
Jadi contohnya:
mendefinisikan tipe enumerasi di mana e (min) adalah 1 dan e (max) adalah 4. Jika tipe yang mendasarinya ditandatangani int, maka bitfield terkecil yang dibutuhkan memiliki 4 bit, dan jika int dalam implementasi Anda adalah pelengkap dua maka rentang valid dari enumnya adalah -8 hingga 7. Jika tipe yang mendasarinya tidak bertanda tangan, maka ia memiliki 3 bit dan kisarannya adalah 0 hingga 7. Periksa dokumentasi compiler Anda jika Anda peduli (misalnya jika Anda ingin memasukkan nilai integral selain enumerator ke jenis yang dicacah, maka Anda perlu mengetahui apakah nilainya berada dalam kisaran pencacahan atau tidak - jika tidak, nilai enumerasi yang dihasilkan tidak ditentukan).
Apakah nilai-nilai tersebut merupakan masukan yang valid untuk fungsi Anda mungkin merupakan masalah yang berbeda dari apakah nilai-nilai tersebut merupakan nilai yang valid dari jenis yang disebutkan. Kode pengecekan Anda mungkin mengkhawatirkan tentang yang pertama daripada yang terakhir, sehingga dalam contoh ini setidaknya harus memeriksa> = A dan <= B.
sumber
Periksa dengan
std::is_signed<std::underlying_type
+ enum tercakup default keint
https://en.cppreference.com/w/cpp/language/enum menyiratkan:
main.cpp
GitHub upstream .
Kompilasi dan jalankan:
Keluaran:
Diuji pada Ubuntu 16.04, GCC 6.4.0.
sumber