C言語 unsignedの使い方

この記事のポイント

この記事ではマイナス値を持たない整数型である、C言語のunsigned型について、基本概念の整理から実際のコードでの活用までを順を追って解説します。

  • unsigned型による符号なし整数の定義と値の範囲
  • 基本的な宣言方法と初期化の構文
  • 実際のプログラムでの活用例とコードサンプル

これらのポイントを理解しておくことで、より効率的かつ安全にプログラミングを行えるようになります。それでは、unsigned型が持つ特徴と利点を、具体的なコード例を交えながら学んでいきましょう。

目次

unsignedとは?

C言語におけるunsignedは、負の値を持たない整数型を表すキーワードです。int型が正負の値を扱えるのに比べ、unsigned int型は 0 以上の値だけを保持します。

符号を持たないという特徴により、unsigned int型は同じビット幅で通常の int型の約2倍の正の値を表現可能です。具体的には32ビットシステムでは、int型が -2,147,483,648 ~ 2,147,483,647を扱えるのに対し、unsigned int型は 0 ~ 4,294,967,295まで対応します。この性質は、unsigned型は配列インデックスやループ制御、ビット演算といった用途に有効です。

【関連】
C言語をもっと詳しく学ぶならpaizaラーニング

基本構文

unsigned型の宣言は、整数型の前にunsignedキーワードを付けるか、unsigned単体で記述する方法があります。最も一般的なのはunsigned intですが、shortやlongと組み合わせることも可能です。初期化方法は通常の整数型と同様ですが、負の値を代入すると警告が表示されたり、予期せぬ動作を招く可能性があります。

#include <stdio.h> int main() { unsigned int count = 100; unsigned short small_num = 50; unsigned long big_num = 1000000; printf("count: %u\n", count); printf("small_num: %hu\n", small_num); printf("big_num: %lu\n", big_num); return 0; }

出力結果

count: 100
small_num: 50
big_num: 1000000

このコード例では、異なるサイズのunsigned型変数を宣言し、それぞれに正の値を代入しています。printf関数では、各unsigned整数型に対応する書式指定子を使用して、正確に表示しています。

実用例

以下では、C言語のunsigned型を実際のプログラムで使用する具体的な例を紹介します。各サンプルコードでは、unsigned型の特徴を活かした実用的な使用場面を示し、コードの動作原理と期待される結果を詳しく解説しました。これらの例を通じて、unsigned型がいかに効果的にプログラムの品質と効率を向上させるかを理解できます。

配列要素の合計計算

配列内の全要素を合計する処理で、インデックスと合計値にunsigned型を使用します。

#include <stdio.h> int main() { unsigned int numbers[] = {10, 20, 30, 40, 50}; unsigned int sum = 0; unsigned int i; for (i = 0; i < 5; i++) { sum += numbers[i]; } printf("合計: %u\n", sum); return 0; }

出力結果

合計: 150

このコードは配列のインデックスと合計値にunsigned型を使用しており、負のインデックスによる意図しないアクセスを防いでいます。ループ変数iも配列の範囲内でのみ動作するため、安全で効率的な処理となっています。

カウンタとしての活用

プログラム実行中のイベント発生回数をカウントする処理です。

#include <stdio.h> int main() { unsigned int cat_count = 0; unsigned int dog_count = 0; char animals[] = {'c', 'd', 'c', 'd', 'c'}; unsigned int i; for (i = 0; i < 5; i++) { if (animals[i] == 'c') cat_count++; else if (animals[i] == 'd') dog_count++; } printf("ネコ: %u匹, イヌ: %u匹", cat_count, dog_count); return 0; }

出力結果

ネコ: 3匹, イヌ: 2匹

カウンタ変数にunsigned型を使用することで、負の値になる心配がなく、より大きな数値まで正確にカウントできます。動物の種類を判定してそれぞれのカウンタを増加させる典型的な集計処理です。

ビット演算での活用

unsigned型はビット演算において特に有用で、論理演算の結果を正確に表現できます。

#include <stdio.h> int main() { unsigned int flag1 = 5; // 0101 (binary) unsigned int flag2 = 3; // 0011 (binary) unsigned int result; result = flag1 & flag2; printf("AND演算結果: %u\n", result); result = flag1 | flag2; printf("OR演算結果: %u\n", result); return 0; }

出力結果

AND演算結果: 1
OR演算結果: 7

このコードではビット単位のAND演算とOR演算を実行しています。unsigned型を使用することで、符号ビットを気にすることなく純粋なビット操作が可能になり、フラグ管理やビットマスク処理で威力を発揮します。

大きな数値の計算

unsigned型の値域の広さを活用して、大きな数値を扱う計算処理です。

#include <stdio.h> int main() { unsigned long mouse_population = 1000; unsigned int months = 6; unsigned int growth_rate = 2; unsigned int i; for (i = 0; i < months; i++) { mouse_population *= growth_rate; } printf("%u ヶ月後のネズミ個体数: %lu\n", months, mouse_population); return 0; }

出力結果

6 ヶ月後のネズミ個体数: 64000

この例ではunsigned long型を使用することで、大きな数値でもオーバーフローが起こりにくくなっています。指数的増加を計算する際に、負の値が発生しないunsigned型の特性が活かされています。

文字列長の計算

文字列の長さを計算する処理で、unsigned型をカウンタとして使用します。この例では日本語文字列のバイト数をカウントしています。

#include <stdio.h> int main() { char animal_name[] = "ライオン"; unsigned int length = 0; while (animal_name[length] != '\0') { length++; } printf("動物名の長さ: %u文字\n", length); return 0; }

出力結果

動物名の長さ: 12文字

unsigned型を使って文字列長が 0 以上であることを明示することで、意図を明確にし、処理の効率化にもつながります。

メモリサイズの管理

データ構造のサイズ計算にunsigned型を活用する例です。

#include <stdio.h> int main() { unsigned int elephant_count = 10; unsigned int elephant_size = 6000; /* kg */ unsigned int total_weight; total_weight = elephant_count * elephant_size; printf("ゾウ%u頭の総重量: %u kg\n", elephant_count, total_weight); if (total_weight > 50000) { printf("重量超過です\n"); } return 0; }

出力結果

ゾウ10頭の総重量: 60000 kg
重量超過です

重量などの物理量を扱う場合、負の値が意味を持たないため、unsigned 型を用いるのが効果的です。ここでは総重量を求め、その値を制限値と照らし合わせています。

インデックス管理

配列やデータ構造のインデックス管理でunsigned型を使用した例です。

#include <stdio.h> int main() { char bird_types[] = {'h', 's', 'e', 'h', 's'}; /* h: hawk, s: sparrow, e: eagle */ unsigned int hawk_positions[5]; unsigned int hawk_count = 0; unsigned int i; for (i = 0; i < 5; i++) { if (bird_types[i] == 'h') { hawk_positions[hawk_count] = i; hawk_count++; } } printf("タカの位置: "); for (i = 0; i < hawk_count; i++) { printf("%u ", hawk_positions[i]); } printf("\n"); return 0; }

出力結果

タカの位置: 0 3

配列の要素位置(インデックス)は、0以上の整数で表されます。そのため、インデックスを扱う変数には、負の値を取らないunsigned型などを活用しつつ、正しく範囲を管理することが重要です。

まとめ

C言語のunsigned型は、符号なし整数を扱うための基本的でありながら非常に有用な機能です。負の値を必要としない場面では、int型よりも広い正の値を表現でき、プログラムの安全性やメモリ効率の向上に役立ちます。

unsignedの活躍する場面

  • 配列インデックスやループカウンタでの境界管理
  • ビット操作やフラグ管理での論理演算処理
  • 大きな正の整数値を扱う数値計算処理

重要なポイント

  • 値域が0以上に限定されることによる安全性向上
  • 同一メモリサイズでの表現可能数値範囲拡大
  • 負の値代入時の予期しない動作への注意が必要

unsigned型を適切に使用することで、プログラムの品質向上とバグの予防につながります。特に配列操作やカウンタ処理では、その特性を最大限に活用できるでしょう。

レベルを更に上げたい方はpaizaプログラミングスキルチェックへ

  1. paizaラーニングトップ
  2. リファレンス
  3. C言語のリファレンス記事一覧
  4. C言語 unsignedの使い方