整数の四則演算
整数の四則演算を行いましょう。整数の足し算・引き算・掛け算・割り算を行います。
int32_t型の値の四則演算
int32_t型で四則演算をしてみましょう。割り算は、結果が小数点にならないところが、ポイントです。小数点は切り捨てられます。
符号あり32bit整数型が表現できる整数の最大値は「2147483647」、最小値は「-2147483648」です。
最大値は「INT32_MAX」、最小値は「INT32_MIN」というマクロで定義されています。
出力する場合はprintf関数のフォーマット指定子に「%d」を指定します。
#include <stdio.h> #include <stdint.h> int main(void) { int32_t num1 = 5; int32_t num2 = 2; int32_t add = num1 + num2; int32_t sub = num1 - num2; int32_t mul = num1 * num2; int32_t div = num1 / num2; printf("add : %d\nsub : %d\nmul : %d\ndiv : %d\n", add, sub, mul, div); }
出力結果です。
add : 7 sub : 3 mul : 10 div : 2
int64_t型の値の四則演算
int64_t型で四則演算をしてみましょう。
符号あり64bit整数型が表現できる整数の最大値は「9223372036854775807」、最小値は「-9223372036854775808」です。
最大値は「INT64_MAX」、最小値は「INT64_MIN」というマクロで定義されています。
出力する場合はprintf関数のフォーマット指定子に「PRId64」を指定します。これは、少し面倒ですが、移植性の問題を回避するためです。
#include <stdio.h> #include <stdint.h> #include <inttypes.h> int main(void) { int64_t num1 = 5; int64_t num2 = 2; int64_t add = num1 + num2; int64_t sub = num1 - num2; int64_t mul = num1 * num2; int64_t div = num1 / num2; printf("add : %" PRId64 "\nsub : %" PRId64 "\nmul : %" PRId64 "\ndiv : %" PRId64 "\n", add, sub, mul, div); }
出力結果です。
add : 7 sub : 3 mul : 10 div : 2
C言語の整数の四則演算の注意点
C言語の整数の四則演算の規則は簡単なように見えて、意外と複雑です。複雑な理由をまず先に書いておきます。
符号あり整数型と符号なし整数型の区別
まず、C言語には、型として、符号あり整数型と符号なし整数型があります。
さて、符号あり整数型と符号なし整数型を演算したら、結果はどうなるのだろうか? 結果の型は、結果の値は? そんな疑問がわいてきますね。
C言語の型の自動変換規則の仕様は、複雑で、覚えておくことは難しく感じます。
ですので、ここでは、まずベストプラクティスを先に書いておきましょう。
符号あり整数型と符号なし整数型を混ぜた演算を行わない
符号あり整数型と符号なし整数型を混ぜた演算は行わない。演算が必要な場合は、型変換によって、符号あり整数型か符号なし整数型にそろえましょう。
整数の演算は符号あり整数型で行う
整数の演算は符号あり整数型で行う。
整数の演算はできる限り符号あり整数型どうしで行います。符号なし64bit整数型であるuint64_t型の演算は、ごくたまに必要になりますが、これ以外の演算は、符号あり64bit以下の整数型(int64_t, int32_t, int16_t, int8_t)で行うことができます。
最初に選択するのは符号あり32bit整数型
整数演算において最初に選択する整数型は、符号あり32bit整数型のint32_tです。
#include <stdint.h> int main(void) { // 符号あり32bit整数型 int32_t num = 3; }
符号あり32bit整数は、整数型の最も基本的な型です。
符号あり32bit整数演算は符号あり64bit整数演算よりもメモリの利用量が少なく、速いです。どれくらい速いのかはわかりませんが、アーキテクチャを考えると64bit整数演算よりも遅くなることはないと考えます。
符号あり64bit整数演算が必要になる場合には、符号あり64bit整数型int64_tを使うようにします。
符号あり16bit整数型と符号あり8bit整数型を選ばないのは、多くの処理系において、これらの型は、符号あり32bit整数に型拡張されCPU上で計算されると想定されるからです。これをC言語仕様では汎整数拡張と呼びます。
C言語の仕様では、int型より小さい符号あり整数型(shortやsigned char)は、intに型拡張されます。C言語のintの仕様における定義は、「最低限16bit幅を持つ整数型」です。ただし、2020年、多くの処理系では、int型は32bitであると想定してもよいでしょう。つまり、32bitより小さい符号あり整数は、符号あり32bit整数に型拡張されると想定してください。
符号あり整数型の演算における自動的な型拡張変換
符号あり整数型どうしの演算では、幅が小さい方の型は、幅が大きい方の型に拡張されて計算されます。
#include <stdint.h> int main(void) { // 符号あり32bit整数型と符号あり64bit整数型の演算 // num1はint64_tに型変換される int32_t num1 = 3; int64_t num2 = 5; int64_t num3 = num1 + num2; }
以下と同じ意味になります。
int64_t num3 = (int64_t)num1 + num2;
符号あり整数型における型の拡張においては、中身の値が変わることはないので、安心できます。
型変換を詳しく知りたい場合は、C言語の型変換規則で解説しています。
整数が最大値を超えたらどうなるの?
整数の最大値に1を加えてみましょう。どうなるでしょうか?
#include <stdio.h> #include <stdint.h> int main(void) { int32_t num = 2147483647; num++; printf("%d\n", num); }
出力結果です。最小値になっています。
-2147483648
負の数が2の補数表現になっている場合は、最大値に1加えると、最小値になります。