整数の四則演算

整数の四則演算を行いましょう。整数の足し算・引き算・掛け算・割り算を行います。

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加えると、最小値になります。

関連情報