CHAR_MAXに設定されたchar値は、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またはCにCHAR_MAX(127)より大きい値を指定するとどうなりますか。charc = 129が-127に変換されるのはなぜですか?彼らは範囲外の値に値を増分するのではなく範囲外の値を割り当てることについて話しているので、この質問には触れません。]


増分は割り当てです。
ウィリアムパーセル

2
charが署名されているか、署名されていないかによって異なります。符号付き整数のオーバーフローは未定義の動作です。したがって、出力は何でもかまいません。
DaBler

回答:


15

問題は2つあります。最初に、

char c = CHAR_MAX;
c += 1;

異なる評価

char c = CHAR_MAX;
c = c + 1;

C11 / C18 6.5.16.2p3のため、答えは「いいえ」ではありません

  1. フォームの複合代入は、左辺値が1回だけ評価されることを除いてE1 op = E2、単純な代入式と同等であり、不確定にシーケンスされた関数呼び出しに関して、複合代入の操作は単一の評価です。がアトミックタイプの場合、複合割り当てはメモリ順序のセマンティクスを持つ読み取り-変更-書き込み操作です。113)E1 = E1 op (E2)E1E1memory_order_seq_cst

次に、問題はで何が起こるかです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に昇格しint、そしてCHAR_MAX == INT_MAX=>はCHAR_MAX + 1、整数オーバーフローが発生し、動作は不定となります

つまり、可能な結果は次のとおりです。

  • 場合はchar、符号なし整数型で、結果は常にある0、すなわちCHAR_MIN

  • それ以外の場合charは符号付き整数型であり、動作は実装定義/未定義です。

    • CHAR_MIN またはその他の実装定義の値、
    • 実装定義のシグナルが発生し、プログラムが終了する可能性があります。
    • または、一部のプラットフォームでは動作が未定義ですsizeof (char) == sizeof (int)

すべてのインクリメント操作はc = c + 1c += 1c++++c同じプラットフォーム上で同じ副作用を持っています。式の評価値は、増分前のc++cになります。他の3つの場合はc、増分後の値になります。


1
sizeof(int) == 1が必要でしょうCHAR_BITS >= 16、そうですか?
sepp2k

3
@ sepp2k <pedantic>IDKについてCHAR_BITSですCHAR_BIT>= 16</pedantic>
Antti Haapala

2
charデフォルトで常に署名されていないもう1つの理由。
chqrlie

1
@chqrlie私は同意しますが、残念ながら、署名されていないことが歴史の後半にあるため、デフォルトで署名されただけかもしれません。EOFがchar ..
Antti Haapala

1
「char_maxに設定されたchar値はCHAR_MINにラップアラウンドすることが保証されていますか?」という直接的な回答を追加することも明らかな場合があります。- >番号
chux -復活モニカ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.