コンテンツにスキップ

C言語/unsigned

出典: フリー教科書『ウィキブックス(Wikibooks)』

概要

[編集]

unsigned は C 言語において整数型の符号を明示的に指定する修飾子であり、符号なし整数 を表します。unsignedunsigned int の省略形として機能し、明示的に符号なしであることを示します。

C 言語の整数型は 符号付き (signed)符号なし (unsigned) の両方が存在します。デフォルトでは int は符号付き (signed int) ですが、unsigned を付けることで符号なし整数として扱うことができます。

unsigned 型の仕様とデフォルトの動作

[編集]
型の宣言 意味
unsigned unsigned int と同義 (符号なし整数)
unsigned int 明示的に符号なし整数を指定
int signed int と同義 (符号付き整数)

例えば、以下の 3 つの宣言はすべて同じ意味を持ちます。

unsigned int a = 100;
unsigned b = 100;  // unsigned int と同義

unsignedint のみならず、他の整数型 (char, short, long, long long) にも適用可能です。

説明
unsigned char 符号なし 8 ビット整数
unsigned short 符号なし 16 ビット整数 (多くの環境で)
unsigned int 符号なし 32 ビット整数 (多くの環境で)
unsigned long 符号なし 32 ビットまたは 64 ビット整数
unsigned long long 符号なし 64 ビット整数

符号なし整数の範囲

[編集]

unsigned 型の範囲は、環境やコンパイラに依存しますが、一般的な 32 ビットおよび 64 ビット環境では以下のようになります。

典型的な範囲 (32 ビット環境)
unsigned char 0 ~ 255
unsigned short 0 ~ 65,535
unsigned int 0 ~ 4,294,967,295
unsigned long 0 ~ 4,294,967,295 (32 ビット環境)
unsigned long long 0 ~ 18,446,744,073,709,551,615

64 ビット環境では unsigned long の範囲が unsigned long long と同じ 64 ビットになることが一般的です。

unsigned の適用と注意点

[編集]

unsigned を使う利点

[編集]
  1. 負の値を扱わないデータに適用
    • unsigned負の値を使用しない整数値 に適しています。
    • 例: 配列のインデックス、サイズ、カウンタ変数 (size_t など)。
  2. 符号ビットを有効活用
    • signed 型と比べて unsigned 型の方が 最大値が 2 倍大きい ため、より広い範囲の数値を格納できます。
  3. ビット演算に適している
    • unsigned 型は ビット単位の演算 (ビットシフトやマスク処理) で意図した動作をしやすい。

unsigned の注意点

[編集]
  1. 符号付き整数との混在に注意
    • signed 型と unsigned 型を混在させると 型変換の問題 が発生する可能性があります。
  2. 負の値を扱えない
    • unsigned 型は負の値を表現できず、0 より小さい値を代入すると オーバーフローが発生 します。


unsigned を使った具体的な例

[編集]

1. unsigned を使用した整数型の宣言

[編集]
#include <stdio.h>
int main() {
    unsigned int a = 3000000000;  // 4,294,967,295 まで OK (32 ビット)
    printf("unsigned int: %u\n", a);
    return 0;
}

出力:

unsigned int: 3000000000

2. signed と unsigned の混在によるバグ

[編集]
#include <stdio.h>
int main() {
    int a = -1;
    unsigned int b = 1;

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

    return 0;
}

一見すると a = -1 なので a < b ( -1 < 1 ) になると思われますが、実際には aunsigned int に型変換され、オーバーフローして 非常に大きな値 になります。そのため、実際の出力は:

a は b 以上

となり、意図しない動作になります。signedunsigned を混ぜる際は型変換に注意が必要です。

3. unsigned のオーバーフロー

[編集]
#include <stdio.h>
int main() {
    unsigned int a = 0;
    a--;

    printf("unsigned int a: %u\n", a);
    return 0;
}

このコードの出力は:

unsigned int a: 4294967295

signed int の場合は -1 になりますが、unsigned int は負の値を持たないため、最大値 (2^32 - 1 = 4,294,967,295) にラップアラウンドされます。

4. unsigned のビット演算

[編集]
#include <stdio.h>
int main() {
    unsigned int a = 5; // 0000 0101
    unsigned int b = 3; // 0000 0011

    printf("a & b: %u\n", a & b); // 0000 0001 -> 1
    printf("a | b: %u\n", a | b); // 0000 0111 -> 7
    printf("a ^ b: %u\n", a ^ b); // 0000 0110 -> 6
    printf("~a: %u\n", ~a);       // 1111 1010 -> 4294967290 (32 ビットの場合)

    return 0;
}

unsigned は負の値を持たないため、ビット演算の結果が直感的になります。

まとめ

[編集]
  • unsignedunsigned int の別名 であり、符号なし整数 を意味する。
  • 負の値を使用しない場合に有用 (例: サイズ、カウンタ、ビット演算)。
  • 符号付き (signed) 型との混在に注意。意図しない型変換が発生する可能性がある。
  • オーバーフロー時の動作が異なる (signed の場合は未定義、unsigned は 0 にループ)。
  • ビット演算に適している

unsigned を適切に活用することで、安全で効率的なプログラムを書くことができます。しかし、符号付き型 (signed) との混在やオーバーフローに注意が必要です。