Apakah nilai char diatur ke CHAR_MAX dijamin untuk membungkus CHAR_MIN?

10

Kode saya:

#include <stdio.h>
#include <limits.h>

int main()
{
    char c = CHAR_MAX;
    c += 1;
    printf("CHAR_MIN=%d CHAR_MAX=%d c=%d (%c)\n", CHAR_MIN, CHAR_MAX, c, c);
}

Keluaran:

CHAR_MIN=-128 CHAR_MAX=127 c=-128 ()

Kita melihat bahwa ketika kita menambah charset variabel ke CHAR_MAX, itu membungkus sekitar CHAR_MIN. Apakah perilaku ini dijamin? Atau apakah itu akan menjadi perilaku yang tidak terdefinisi atau perilaku yang ditentukan implementasi? Apa yang dikatakan standar C99 tentang ini?

[Catatan: Apa yang terjadi ketika memberi nilai lebih besar dari CHAR_MAX (127) ke char atau C- mengapa char c = 129 akan dikonversi menjadi -127? tidak menjawab pertanyaan ini karena mereka berbicara tentang menetapkan nilai out-of-range tidak menambah nilai ke nilai out-of-range.]

Lone Learner
sumber
Selisih adalah tugas.
William Pursell
2
Itu tergantung pada apakah char ditandatangani atau tidak. Overflow bilangan bulat yang ditandatangani adalah perilaku yang tidak terdefinisi. Jadi hasilnya bisa apa saja.
DaBler

Jawaban:

15

Pertanyaannya ada dua: Pertama

char c = CHAR_MAX;
c += 1;

dievaluasi berbeda dari

char c = CHAR_MAX;
c = c + 1;

dan jawabannya adalah tidak , karena C11 / C18 6.5.16.2p3 :

  1. Penugasan majemuk dari formulir E1 op = E2setara dengan ekspresi penugasan sederhana E1 = E1 op (E2)kecuali bahwa nilai E1dievaluasi hanya sekali, dan sehubungan dengan pemanggilan fungsi yang tidak ditentukan urutannya, operasi penugasan majemuk adalah evaluasi tunggal. Jika E1memiliki tipe atom, penugasan majemuk adalah operasi baca-modifikasi-tulis dengan memory_order_seq_cstsemantik urutan memori. 113)

Lalu, pertanyaannya adalah apa yang terjadi di c = c + 1. Di sini operan untuk +menjalani konversi aritmatika biasa, dan cdan 1karenanya dipromosikan int, kecuali jika arsitektur yang benar-benar aneh mengharuskan yang chardipromosikan unsigned int. Perhitungan +kemudian dievaluasi, dan hasilnya, jenis int/ unsigned intdikonversi kembali ke chardan disimpan dalam c.

Ada 3 cara yang ditentukan implementasi yang kemudian dapat dievaluasi:

  • CHAR_MINadalah 0 dan karenanya chartidak ditandatangani.

    Entah charkemudian dipromosikan ke intatau unsigned intdan jika dipromosikan ke int, maka CHAR_MAX + 1tentu akan cocok menjadi intterlalu, dan tidak akan meluap, atau jika unsigned intmungkin cocok atau membungkus ke nol. Ketika nilai yang dihasilkan, yang secara numerik baik CHAR_MAX + 1atau 0setelah pengurangan modulo, kembali ke c, setelah pengurangan modulo itu akan menjadi 0, yaituCHAR_MIN

  • Jika chartidak ditandatangani, maka jika CHAR_MAX lebih kecil dari INT_MAX, hasil CHAR_MAX + 1akan cocok int, dan standar C11 / C18 6.3.1.3p3 berlaku untuk konversi yang terjadi pada penugasan :

    1. Jika tidak, tipe baru ditandatangani dan nilainya tidak dapat diwakili di dalamnya; baik hasilnya adalah implementasi yang ditentukan atau sinyal implementasi yang ditetapkan dinaikkan.
  • Atau, jikaf sizeof (int) == 1 dan char ditandatangani, maka chardipromosikan ke int, dan CHAR_MAX == INT_MAX=> CHAR_MAX + 1akan menyebabkan bilangan bulat bilangan bulat dan perilaku akan tidak terdefinisi .

Yaitu hasil yang mungkin adalah:

  • Jika charadalah tipe integer yang tidak ditandatangani, hasilnya selalu 0, yaitu CHAR_MIN.

  • Jika tidak, charmerupakan tipe integer yang ditandatangani, dan perilaku didefinisikan-didefinisikan / tidak didefinisikan:

    • CHAR_MIN atau beberapa nilai yang ditentukan implementasi lainnya,
    • sinyal yang ditentukan implementasi dinaikkan, mungkin mengakhiri program,
    • atau perilaku tidak terdefinisi pada beberapa platform di mana sizeof (char) == sizeof (int).

Semua operasi increment c = c + 1, c += 1, c++dan ++cmemiliki efek samping yang sama pada platform yang sama. Nilai ekspresi yang dievaluasi c++akan menjadi nilai csebelum kenaikan; untuk tiga lainnya, itu akan menjadi nilai csetelah kenaikan.

Antti Haapala
sumber
1
sizeof(int) == 1akan membutuhkan CHAR_BITS >= 16, kan?
sepp2k
3
@ sepp2k <pedantic>IDK tentang CHAR_BITStetapi CHAR_BITakan >= 16</pedantic>.
Antti Haapala
2
Satu alasan lagi mengapa charharus selalu tidak ditandatangani secara default.
chqrlie
1
@ chqrlie Saya setuju, sayangnya mungkin saja itu ditandatangani secara default karena unsigned ada di akhir sejarah, mungkin terlalu sulit untuk diubah sekarang pada beberapa sistem cr * ppy karena banyaknya program yang rusak yang mengharapkan EOF untuk dimasukkan ke dalam char ..
Antti Haapala
1
Terkadang jelas juga untuk menambahkan jawaban langsung: "Apakah nilai char diatur ke CHAR_MAX dijamin untuk dibungkus ke CHAR_MIN?" -> No.
chux - Pasang kembali Monica