私はこの質問が何億回も質問され、答えられたように見えることを知っていますが、私自身の経験に答えを一致させることができないようです。
C規格では、加算のために「両方のオペランドは算術型でなければならない」(6.5.6.1)と規定されています。Arithemitc型は整数型と浮動型(6.2.5.18)をカバーし、最後に整数型はchar、short、int、long、long longであり、符号付き型と符号なし型(6.2.5.4と6.2.5.6)として存在します。通常の算術変換の規則によれば、「両方のオペランドが同じタイプの場合、それ以上の変換は必要ありません」。ここまでは順調ですね。
ここで「TheCBook」から例示されているように、汎整数拡張が適用される「[n]o演算はintよりも短い精度でCによって実行される」というのが私の理解です。私はこれを何度も見たようですが、標準ではこれへの言及を見つけることができません。
unsigned charは算術型であり、通常の算術変換の規則では、同じ型のオペランドは変換を必要としないと規定されているので、なぜ汎整数拡張が必要なのでしょうか。
2つの異なるコンパイラを使用してこれをテストしました。私はcharの加算を行う簡単なプログラムを書きました:
unsigned char a = 1;
unsigned char b = 2;
unsigned char c = a + b;
ターゲットプラットフォームは、8ビットアーキテクチャを使用するAtmelMega8uCです。したがって、オペランドを汎整数拡張の対象にする必要がある場合は、整数加算では2つのレジスタを使用する必要があります。
最適化を行わず、厳密なANSI C移植性オプションを有効にして、imagecraft avrコンパイラを使用してこれをコンパイルすると、次のアセンブリコードが生成されます。
mov R16, R20
add R16, R18
avr-gccの使用(gccの-strictに似たANSIスイッチを認識していません):
$ avr-gcc -O0 -mmcu=atmega8 -S -c main.c
結果のアセンブリ:
ldd r25,Y+1
ldd r24,Y+2
add r24,r25
std Y+3,r24
どちらの場合も、結果のコードは1バイトで動作します。ビットごとに同様の結果が得られます| および&および論理|| と &&。これは、標準が汎整数拡張なしで文字タイプの算術演算を許可することを意味しますか、それとも単にこれらのコンパイラが標準に準拠していないことを意味しますか?
追加:
結果が格納されているタイプによって異なります。上記の例は、結果がcharに格納されている場合にのみ当てはまり、加算の結果には依存しません。aを0xFFに設定し、bを1に設定すると、まったく同じアセンブリコードが生成されます。
cのタイプがunsignedintに変更された場合、結果のアセンブリは次のようになります。
mov R2,R20
clr R3
mov R16,R18
clr R17
add R16,R2
adc R17,R3
結果を1バイトに保持できる場合、つまりa=1およびb=2の場合でも。