私のコード:
#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型に何が起こるか、char型のC = 129が-127に変換されますなぜC-?彼らは範囲外の値に値をインクリメントしない範囲外の値を割り当てることについて話しているため、この問題に対処していません。]
質問は2つあり:第一に、あります
char c = CHAR_MAX;
c += 1;
とは異なって評価
char c = CHAR_MAX;
c = c + 1;
そして答えは何のことはないではない、なぜならC11 / C18 6.5.16.2p3:
- フォームの化合物の割り当ては
E1 op = E2
、単純な代入式と等価であるE1 = E1 op (E2)
左辺値は点を除いてE1
、一度だけ評価され、不定順関数呼び出しに対して、複合代入の動作は、1つの評価です。場合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は時起こる変換に適用割付:- そうでなければ、新しいタイプが署名され、その値はで表すことができません。結果は実装定義であるか、または実装定義信号が発生されますか。
または、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 + 1
、c += 1
、c++
と++c
同じプラットフォーム上で同じ副作用を持っています。式の評価値は、c++
の値になりますc
増分の前に。他の3のために、それはの値になりますc
インクリメント後。