-2147483648 adalah bilangan bulat terkecil untuk tipe bilangan bulat dengan 32 bit, tetapi tampaknya akan meluap dalam if(...)
kalimat:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Ini akan dicetak true
dalam pengujian saya. Namun, jika kita menggunakan -2147483648 ke integer, hasilnya akan berbeda:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Ini akan dicetak false
.
Saya bingung. Adakah yang bisa memberikan penjelasan tentang ini?
Pembaruan 02-05-2012:
Terima kasih atas komentar Anda, di kompiler saya, ukuran int adalah 4 byte. Saya menggunakan VC untuk beberapa pengujian sederhana. Saya telah mengubah uraian dalam pertanyaan saya.
Itu banyak balasan yang sangat baik dalam posting ini, AndreyT memberikan penjelasan yang sangat rinci tentang bagaimana perilaku kompiler pada input tersebut, dan bagaimana integer minimum ini diimplementasikan. qPCR4vir di sisi lain memberikan beberapa "keingintahuan" terkait dan bagaimana bilangan bulat diwakili. Sangat mengesankan!
sumber
INT_MIN
dari-9223372036854775808
, jikaCHAR_BIT
adalah 16. Dan bahkan denganCHAR_BIT == 8
dansizeof(int
== 4) `Anda mungkin mendapatkan-9223372036854775807
karena C tidak memerlukan 2-Complement angka.Jawaban:
-2147483648
bukan "angka". Bahasa C ++ tidak mendukung nilai literal negatif.-2147483648
sebenarnya adalah ekspresi: nilai literal positif2147483648
dengan-
operator unary di depannya. Nilai2147483648
tampaknya terlalu besar untuk sisi positifint
jangkauan di platform Anda. Jika tipelong int
memiliki jangkauan yang lebih besar pada platform Anda, kompiler harus secara otomatis menganggap bahwa2147483648
adalong int
tipe. (Dalam C ++ 11 kompiler juga harus mempertimbangkanlong long int
jenis.) Ini akan membuat kompiler untuk mengevaluasi-2147483648
dalam domain tipe yang lebih besar dan hasilnya akan negatif, seperti yang diharapkan.Namun, ternyata dalam kasus Anda rentangnya
long int
sama dengan rentangint
, dan secara umum tidak ada tipe integer dengan rentang lebih besar dariint
pada platform Anda. Ini secara formal berarti bahwa konstanta positif2147483648
meluap semua jenis integer yang ditandatangani yang tersedia, yang pada gilirannya berarti bahwa perilaku program Anda tidak terdefinisi. (Agak aneh bahwa spesifikasi bahasa memilih untuk perilaku yang tidak terdefinisi dalam kasus-kasus seperti itu, alih-alih membutuhkan pesan diagnostik, tetapi begitulah adanya.)Dalam praktiknya, dengan mempertimbangkan bahwa perilaku tersebut tidak terdefinisi,
2147483648
dapat ditafsirkan sebagai beberapa nilai negatif yang bergantung pada implementasi yang berubah menjadi positif setelah-
diterapkan secara unary . Sebagai alternatif, beberapa implementasi mungkin memutuskan untuk mencoba menggunakan tipe yang tidak ditandatangani untuk mewakili nilai (misalnya, dalam kompiler C89 / 90 diharuskan untuk digunakanunsigned long int
, tetapi tidak dalam C99 atau C ++). Implementasi diperbolehkan untuk melakukan apa saja, karena perilaku itu tidak ditentukan.Sebagai catatan, inilah alasan mengapa konstanta seperti
INT_MIN
biasanya didefinisikan sebagaibukannya yang tampaknya lebih mudah
Yang terakhir tidak akan berfungsi sebagaimana dimaksud.
sumber
#define INT_MIN (-2147483647 - 1)
.int
. Implementasi OP mungkin tidak memiliki tipe 64-bit.-1.0
diuraikan sebagai nilai ganda negatif, bukan?unsigned long int
dalam konteks ini, tetapi dalam C99 izin ini dihapus. Literal yang tidak terhubung dalam C dan C ++ harus memiliki tipe yang sudah ditandatangani . Jika Anda melihat tipe yang tidak ditandatangani di sini ketika yang ditandatangani akan berfungsi, itu berarti kompiler Anda rusak. Jika Anda melihat tipe yang tidak ditandai di sini saat tidak ada tipe yang ditandatangani, maka ini hanyalah manifestasi spesifik dari perilaku yang tidak terdefinisi.Compiler (VC2012) mempromosikan ke integer "minimum" yang dapat menyimpan nilai-nilai. Dalam kasus pertama,
signed int
(danlong int
) tidak bisa (sebelum tanda diterapkan), tetapiunsigned int
dapat:2147483648
memilikiunsigned int
???? Tipe. Di detik Anda memaksaint
dariunsigned
.Berikut ini "keingintahuan" terkait:
Standar C ++ 11 :
...
...
Dan ini adalah aturan promosi untuk bilangan bulat dalam standar.
sumber
int
,long int
,unsigned long int
untuk mewakili konstanta desimal unsuffixed. Itu adalah satu-satunya bahasa yang memungkinkan menggunakan tipe yang tidak ditandatangani untuk konstanta desimal yang tidak tetap. Di C ++ 98 ituint
ataulong int
. Tidak ada tipe yang tidak ditandatangani diizinkan. Baik C (mulai dari C99) maupun C ++ tidak mengizinkan kompiler untuk menggunakan tipe yang tidak ditandatangani dalam konteks ini. Kompiler Anda, tentu saja, bebas untuk menggunakan tipe yang tidak ditandatangani jika tidak ada yang ditandatangani bekerja, tetapi ini masih hanya manifestasi spesifik dari perilaku yang tidak terdefinisi.int
ataulong int
untuk mewakili2147483648
. Juga, AFAIK, di VC2012 keduanyaint
danlong int
tipe 32-bit. Ini berarti bahwa dalam VC2012 literal2147483648
harus mengarah pada perilaku yang tidak terdefinisi . Ketika perilaku tidak terdefinisi, kompiler diizinkan untuk melakukan apa saja. Itu berarti VC2012 tidak rusak. Itu hanya mengeluarkan pesan diagnostik yang menyesatkan. Alih-alih memberi tahu Anda bahwa perilaku tidak jelas, ia memutuskan untuk menggunakan tipe yang tidak ditandatangani.long
, dan tidak diharuskan mengeluarkan diagnostik? Itu akan tampak rusak.Dalam pendek,
2147483648
berlimpah-limpah-2147483648
, dan(-(-2147483648) > 0)
adalahtrue
.Ini adalah bagaimana
2147483648
penampilan seperti dalam biner.Selain itu, dalam kasus perhitungan biner yang ditandatangani, bit yang paling signifikan ("MSB") adalah bit tanda. Pertanyaan ini dapat membantu menjelaskan alasannya.
sumber
Karena
-2147483648
sebenarnya2147483648
dengan negasi (-
) yang diterapkan padanya, angkanya tidak seperti yang Anda harapkan. Ini sebenarnya sama dengan pseudocode ini:operator -(2147483648)
Sekarang, anggap kompiler Anda
sizeof(int)
sama dengan4
danCHAR_BIT
didefinisikan sebagai8
, yang akan membuat2147483648
melimpahi nilai maksimum yang ditandatangani integer (2147483647
). Jadi, apa plus maksimum satu? Mari kita selesaikan dengan integer pujian 2s, 2s.Tunggu! 8 melebihi integer! Apa yang kita lakukan? Gunakan representasi unsigned dari
1000
dan menafsirkan bit sebagai integer yang ditandatangani. Representasi ini membuat kita-8
menerapkan negasi komplemen 2s yang menghasilkan8
, yang, seperti kita ketahui, lebih besar dari0
.Inilah sebabnya
<limits.h>
(dan<climits>
) biasanya didefinisikanINT_MIN
sebagai((-2147483647) - 1)
- sehingga bilangan bulat bertanda maksimum (0x7FFFFFFF
) dinegasikan (0x80000001
), lalu dikurangi (0x80000000
).sumber
-8
masih-8
.-(8)
yang dalam C ++ sama dengan-8
- itu negasi diterapkan pada literal, bukan literal negatif. Secara literal adalah8
, yang tidak sesuai dengan bilangan bulat 4-bit yang ditandatangani, jadi harus tidak ditandatangani. Polanya adalah1000
. Sejauh ini jawaban Anda benar. Negasi komplemen keduanya1000
dalam 4 bit adalah1000
, tidak masalah apakah itu ditandatangani atau tidak. Jawaban Anda, mengatakan "menafsirkan bit sebagai bilangan bulat yang ditandatangani" yang membuat nilai-8
setelah negasi komplemen keduanya, sama seperti sebelum negasi.8
. Negasi diterapkan (modulo 16), menghasilkan jawaban akhir8
. Pengkodean masih 1000 tetapi nilainya berbeda karena jenis yang tidak ditandatangani dipilih.