C言語の unsigned を徹底解説!使い方・注意点・よくある誤解を完全ガイド

はじめに

C言語では、整数型のデータを扱う際に「符号付き(signed)」と「符号なし(unsigned)」の2つの種類が存在します。特に unsigned 型は、負の値を持たない整数型 として扱われ、特定の用途で非常に有用です。しかし、その特性を理解せずに使用すると、思わぬバグを引き起こすこともあります。

この記事では、C言語における unsigned の使い方や注意点について詳しく解説します。具体的なコード例を交えながら、unsigned の利点とリスクを理解し、適切に活用できるようになりましょう。

unsigned とは?基本の理解

unsigned とは?

C言語では、整数型(intchar など)に unsigned を指定することで、符号なし(負の値を持たない)整数型 として扱うことができます。

例えば、通常の int 型(符号付き)は、以下のような範囲の値を扱うことができます。

int 型(32bit環境の場合)
-2,147,483,648 〜 2,147,483,647

一方、unsigned int 型は、負の数を持たない代わりに、より広い範囲の正の値を扱うことができます。

unsigned int 型(32bit環境の場合)
0 〜 4,294,967,295

つまり、unsigned を使うことで、より大きな値を格納できるようになります。

unsigned の基本的な宣言方法

unsigned を使用する際は、以下のようにデータ型の前に unsigned を付けて宣言します。

#include <stdio.h>

int main() {
    unsigned int num = 3000000000;
    printf("%u\n", num);  // 3000000000
    return 0;
}

このように、unsigned を使うことで、通常の int よりも大きな値を扱うことができます。

unsigned のデータ型と表現範囲

unsigned の種類と範囲

C言語では、unsigned は複数のデータ型に適用できます。それぞれの型のサイズと範囲は、以下の表の通りです。

データ型サイズ(バイト)範囲
unsigned char10 ~ 255
unsigned short20 ~ 65,535
unsigned int40 ~ 4,294,967,295
unsigned long4 または 8環境による
unsigned long long80 ~ 18,446,744,073,709,551,615

サイズは環境によって異なる ため、常に sizeof() を使用して確認するのがベストです。

#include <stdio.h>

int main() {
    printf("Size of unsigned int: %zu bytes\n", sizeof(unsigned int));
    return 0;
}

unsigned の使用例

実際に unsigned を利用して、数値の最大値を確認してみましょう。

#include <stdio.h>
#include <limits.h>

int main() {
    printf("Max unsigned int: %u\n", UINT_MAX);
    return 0;
}

このコードを実行すると、環境に応じた unsigned int の最大値が出力されます。

unsigned の基本的な使い方

unsigned の宣言と代入

unsigned を使用する際には、次のように変数を宣言します。

#include <stdio.h>

int main() {
    unsigned int num1 = 100;
    unsigned int num2 = 200;

    printf("num1: %u\n", num1);
    printf("num2: %u\n", num2);

    return 0;
}

このプログラムでは、unsigned int 型の変数 num1num2 を宣言し、それぞれ 100 と 200 の値を代入しています。

unsigned を使用する際の注意点

signed と unsigned の混在によるバグ

符号付き整数 (int) と unsigned int を比較すると、予期しない結果が生じる可能性があります。

#include <stdio.h>

int main() {
    int a = -5;  // 符号付き
    unsigned int b = 10;  // 符号なし

    if (a < b) {
        printf("a は b より小さい\n");
    } else {
        printf("a は b より大きい\n");
    }

    return 0;
}

このコードでは、a-5 なので b=10 よりも小さいはずですが、aunsigned int に変換されてしまい、意図しない比較結果になります。

侍エンジニア塾

unsigned を使うべき場面と避けるべき場面

unsigned を使うべき場面

負の値を考慮する必要がない場合(例:バイナリデータ処理)
メモリ効率を最適化したい場合(例:組み込みシステム)
ビット演算を多用する場合(例:フラグ管理)

unsigned を避けるべき場面

符号付き変数と混在させる場合(意図しない型変換が発生)
負の値を扱う可能性がある場合(意図しないバグを生む)
ループ変数として使用する場合(オーバーフローのリスク)

よくある誤解とその対処法(FAQ)

unsigned を使うと計算が速くなる?

誤解
unsigned を使うと、signed よりも演算が速くなる」と考えられることがあります。

正解
現代のCPUでは、unsignedsigned の演算速度に違いはほぼありません

対策
unsigned を使うかどうかは 計算速度ではなく、データの意味に基づいて判断 しましょう。

まとめ

ここまで、unsigned に関する よくある誤解とその対処法 を紹介しました。

この記事のポイント

  • unsigned は計算速度を向上させるわけではない
  • signed との変換は注意が必要(特にオーバーフロー時の挙動)。
  • ループ変数に unsigned を使うと無限ループのバグが発生することがある
  • unsigned char はバイナリデータの処理に適している
  • 負の値を unsigned に代入すると意図しない動作をする

これらを理解しておけば、C言語で unsigned を適切に使いこなすことができます。