C言語の型は、次の3種類に分類される。
型をいくつかまとめた呼び方として、他によく使われるのは、次のようなものである。
(signed,unsignedはs_,u_と略した)
符号付き 符号無し
整数型 整数型 文字型 汎整数型 算術型 スカラ型
s_char O O O O O
short O O O O
int O O O O
long O O O O
u_char O O O O O
u_short O O O O
u_int O O O O
u_long O O O O
float O O
double O O
long double O O
char O O O O
列挙型 O O O
ポインタ型 O
(文字型は3種類あることに注意。これらは別々の型である。)
問: C99で追加された、_Bool、long long、unsigned long longはどれに含まれるか調べよ。
汎整数型は、単項演算子~、二項演算子<<,>>,&,^,|,%、ポインタに加減する値、switch文の制御式などに使われる。配列宣言の[]の中やの式や、case名札の式は、汎整数定数式である。
算術型は演算子+,-,*,/などに使われる。
スカラ型は、キャスト演算子、演算子++,--,!,&&,||、if文の制御式、while文の制御式などに使われる。
型については、非修飾型(これまでに述べた型)と修飾版(constとvolatileの一方または両方を付けた型)の区別もある。
整数定数の型は、次の並びのうちでその値を表現できる最初の型になる。
問: C99ではどのように変更されたか調べよ(long long、unsigned long longの追加など)。
小数点と指数部の少なくとも一つがあるなら、浮動小数点定数である(0で始まっても8進数として解釈されない)。
問: 列挙定数として宣言された識別子の型は何か。
問: 単純文字定数の型は何か。(C++では異なる)
問: 単純文字列リテラルの型は何か。
sizoef演算子の結果は、size_tという符号無し整数型である。
二つのポインタの減算の結果は、ptr_diff_tという符号付き整数型である(結果がptr_diff_tに収まらなかった場合の動作は未定義)。
Coinでは今のところ扱わないが、ワイド文字定数の持つ型、ワイド文字列リテラルに対する配列の要素の型は、wchar_tという汎整数型である。
long double, double, float, unsigned long, long, unsigned int, intただし、一つ例外がある。longとunsigned intの組合せで、longがunsigned intのすべての値を表現できないときに限り、unsigned longにそろえる。
問: C99ではどうなったか。
Coinsでは、この変換を表すために、HIRにdecay演算子を導入して、変換を明示する。
まず、nビット符号なし数aの最上位ビットをsとするとき、同じビット並びの符号つき数の値は、
a-2nsであることに注意しておく。すると、nビット符号なし数a,bがあるとき、それぞれの最上位ビットをs,tとすれば、符号なしの積は、
ab符号つきの積は、
(a-2ns)(b-2nt)となる。後者を変形すると、
ab-2n(bs+at)+22nとなり、ab以外の項は下位nビットに影響を与えない。つまり、下位nビットはabであり、符号なしの場合と同じであることが示された。
多くの処理系では(C99では必ず)、商は0方向に切り捨てられる。これは、算術右シフトの動作と異なるため、除算をシフトで置き換えるには、次のような補正が必要となる。
a/2n → (a>=0 ? a : a+2n-1)>>n
なお、(a/b)*b+a%bはaと等しくなければならないので、余りも補正が必要である。
a%2n → a-((a>=0 ? a : a+2n-1)&-2n)