CHAR_MAX değerine göre bir char değerinin CHAR_MIN değerine çevrilmesi garanti ediliyor mu?


10

Kodum:

#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);
}

Çıktı:

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

Bir chardeğişken setini artırdığımızda, değişkenin CHAR_MAXetrafına sarıldığını görürüz CHAR_MIN. Bu davranış garanti ediliyor mu? Yoksa tanımlanmamış davranış mı yoksa uygulama tarafından belirlenen davranış mı olacak? C99 standardı bu konuda ne diyor?

[Not: CHAR_MAX (127) 'den daha büyük bir değeri char veya C'ye verirseniz, char c = 129 neden -127'ye dönüşür? bu soruyu ele almaz çünkü aralık dışı bir değere bir değer eklemeyen aralık dışı bir değer atamaktan bahseder.]


Artış bir ödevdir.
William Pursell

2
Karakterin imzalı veya imzasız olmasına bağlıdır. İşaretli tamsayıların taşması tanımsız bir davranıştır. Böylece çıktı herhangi bir şey olabilir.
DaBler

Yanıtlar:


15

Soru iki yönlüdür: Birincisi,

char c = CHAR_MAX;
c += 1;

farklı değerlendirildi

char c = CHAR_MAX;
c = c + 1;

ve cevap hayır değil , çünkü C11 / C18 6.5.16.2p3 :

  1. Formun bir bileşik ataması E1 op = E2, basit değerin ifade edilmesine eşdeğerdir E1 = E1 op (E2), ancak lvalue E1sadece bir kez değerlendirilir ve belirsiz bir şekilde dizilenmiş bir fonksiyon çağrısına göre, bir bileşik atamasının çalışması tek bir değerlendirmedir. Eğer E1bir atom türü vardır, bileşik atama ile salt değiştirme-yazma operasyonu memory_order_seq_cstbellek sipariş anlam. 113)

O zaman soru ne oluyor c = c + 1. Burada işlenenler +olağan aritmetik dönüşümlere uğrayacak cve 1bu nedenle int, gerçekten tuhaf bir mimari gerektirmediği sürece charterfi edilmektedir unsigned int. Daha +sonra hesaplanması değerlendirilir ve int/ türünün sonucu unsigned intgeri dönüştürülür charve içinde saklanır c.

Orada 3 bu daha sonra değerlendirilebilir hangi uygulama tanımlı yolları:

  • CHAR_MIN0 charolduğundan imzasızdır.

    Ya charsonra terfi edilir intveya unsigned intve bir terfi durumunda int, o zaman CHAR_MAX + 1mutlaka bir sığacak intkadar değil, taşma veya eğer unsigned intsığdırmak veya sıfıra etrafına sarmak olabilir. Sayısal olarak ya modulo indirgeme işleminden sonra ya CHAR_MAX + 1da 0sonra ortaya çıkan değer, modulo indirgeme cişleminden sonra 0 olur, yaniCHAR_MIN

  • Aksi charimzalanmış ise, o zaman CHAR_MAX daha küçük INT_MAX, sonucu CHAR_MAX + 1bir uyacak intve standart C11 / C18 6.3.1.3p3 üzerine olur dönüşüm için geçerlidir atama :

    1. Aksi takdirde, yeni tür imzalanır ve değer, içinde temsil edilemez; sonuç uygulama tarafından tanımlanır veya uygulama tarafından tanımlanan bir sinyal oluşturulur.
  • Veya iff sizeof (int) == 1 ve char imzalı, daha sonra a charolarak yükseltilir intve CHAR_MAX == INT_MAX=> CHAR_MAX + 1tamsayı taşmasına neden olur ve davranış tanımsız olur .

Yani olası sonuçlar:

  • Eğer charbir işaretsiz tamsayı türüdür, sonuç her zaman 0yani CHAR_MIN.

  • Aksi takdirde char, işaretli bir tamsayı türüdür ve davranış, uygulama tanımlı / tanımsızdır:

    • CHAR_MIN veya başka bir uygulama tanımlı değer,
    • uygulama tarafından tanımlanan bir sinyal ortaya çıkar ve muhtemelen programı sonlandırır,
    • veya bazı platformlarda davranış tanımsızdır sizeof (char) == sizeof (int).

Tüm artış işlemleri c = c + 1, c += 1, c++ve ++caynı platform üzerinde aynı yan etkileri vardır. İfadenin değerlendirilen değeri, artıştan c++önceki değer olacaktır c; diğer üçü için bu cartıştan sonraki değer olacaktır .


1
sizeof(int) == 1gerektirirdi CHAR_BITS >= 16, değil mi?
sepp2k

3
@ sepp2k <pedantic>IDK hakkında CHAR_BITSama CHAR_BITolur >= 16</pedantic>.
Antti Haapala

2
Neden charher zaman varsayılan olarak imzalanmamış olmalıdır.
chqrlie

1
@chqrlie Kabul ediyorum, maalesef varsayılan olarak imzalanmış olabilir, çünkü imzasız tarihin ilerleyen zamanlarındaydı, EOF'nin bir sığınağa girmesini bekleyen çok sayıda kırık program nedeniyle şimdi bazı cr * ppy sistemlerinde değiştirmek çok zor olabilir. char ..
Antti Haapala

1
Bazen doğrudan bir yanıt eklemek de açıktır: "CHAR_MAX olarak ayarlanmış bir char değerinin CHAR_MIN'e çevrilmesi garanti ediliyor mu?" -> Hayır.
chux - Monica
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.