Чи гарантовано значення char, встановлене на CHAR_MAX, і воно гарантовано завершиться до CHAR_MIN?


10

Мій код:

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

Вихід:

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

Ми бачимо, що коли ми збільшуємо charнабір змінної CHAR_MAX, вона обертається на CHAR_MIN. Чи гарантована така поведінка? Або це буде невизначена поведінка або конкретна поведінка? Що говорить про це стандарт C99?

[Примітка: Що трапляється, коли значення, що перевищує CHAR_MAX (127), значення char або C- чому char c = 129 перетвориться на -127? це питання не стосується, оскільки вони говорять про присвоєння значення поза діапазоном, не збільшуючи значення до значення поза діапазоном.]


Приріст - це призначення.
Вільям Перселл

2
Це залежить від того, підписаний знак чи без підпису. Переповнення підписаних цілих чисел - це невизначена поведінка. Тож вихід може бути будь-яким.
DaBler

Відповіді:


15

Питання двояке: По-перше, це

char c = CHAR_MAX;
c += 1;

оцінюється інакше від

char c = CHAR_MAX;
c = c + 1;

а відповідь - ні, це не так , тому що C11 / C18 6.5.16.2p3 :

  1. Складене присвоєння форми E1 op = E2еквівалентне простому вираженню присвоєння, E1 = E1 op (E2)за винятком того, що значення значення E1оцінюється лише один раз, а щодо невизначено послідовного виклику функції операція складеного призначення є єдиною оцінкою. Якщо E1має атомний тип, складене призначення - це операція читання-зміна-запис із memory_order_seq_cstсемантикою порядку пам'яті. 113)

Потім, питання в тому, що відбувається в c = c + 1. Тут операнди +пройти звичайні арифметичні перетворення, а cй 1, отже , підвищені до int, якщо дійсно безглузда архітектура не вимагає, charпідвищена до unsigned int. Потім обчислюється +обчислення, а результат, тип int/ unsigned intперетворюється назад charі зберігається в c.

Існує 3 способи, визначені реалізацією, за допомогою яких це можна потім оцінити:

  • CHAR_MINдорівнює 0 і тому charне підписується.

    Або charпросувається, intабо, unsigned intякщо він просувається до int, він CHAR_MAX + 1обов'язково впишеться в intзанадто, і не переповниться, або якщо unsigned intвін може поміститися або обернутися до нуля. Коли отримане значення, яке чисельно CHAR_MAX + 1або 0після зменшення модуля, повернеться до c, після зменшення модуля воно стане 0, тобтоCHAR_MIN

  • В іншому випадку charпідписується, тоді, якщо CHAR_MAX він менший INT_MAX, результат CHAR_MAX + 1підходить int, і стандарт C11 / C18 6.3.1.3p3 застосовується до перетворення, що відбувається при призначенні :

    1. В іншому випадку новий тип підписаний, і значення не може бути представлено в ньому; або результат визначений реалізацією, або підвищений сигнал, визначений реалізацією.
  • Або, якщо iff sizeof (int) == 1 і char підписано, тоді він charбуде переведений на an int, і CHAR_MAX == INT_MAX=> CHAR_MAX + 1викличе ціле переповнення і поведінка буде невизначена .

Тобто можливими результатами є:

  • Якщо charце непідписаний цілочисельний тип, результат завжди є 0, тобто CHAR_MIN.

  • В іншому випадку charце підписаний цілочисельний тип, а поведінка визначено / не визначено:

    • CHAR_MIN або якесь інше значення, визначене реалізацією,
    • піднімається визначений реалізацією сигнал, можливо, припиняючи програму,
    • або поведінка не визначена на деяких платформах, де sizeof (char) == sizeof (int).

Всі операції інкремента c = c + 1, c += 1, c++і ++cмають ті ж побічні ефекти на тій же платформі. Оцінене значення виразу c++буде значенням cдо збільшення; для інших трьох це буде значення cпісля приросту.


1
sizeof(int) == 1зажадає CHAR_BITS >= 16, правда?
sepp2k

3
@ sepp2k <pedantic>IDK про, CHAR_BITSале CHAR_BITхотів би >= 16</pedantic>.
Антті Хаапала

2
Ще одна причина, чому charзавжди має бути непідписаний за замовчуванням.
chqrlie

1
@chqrlie Я погоджуюся, на жаль, це може бути лише те, що він був підписаний за замовчуванням, тому що підписаний був пізніше в історії, може бути надто складно змінити зараз на деяких системах cr * ppy через велику кількість зламаних програм, очікуючи, що EOF впишеться в char ..
Антті Хаапала

1
Іноді зрозуміло також додати пряму відповідь: "Чи гарантовано, що значення char встановлено на CHAR_MAX, щоб перетворитись на CHAR_MIN?" -> Ні
chux
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.