C言語のhugeポインタ(巨大ポインタ)とは?near・farポインタとの違いを解説
はじめに:ポインタの3つの種類
C言語では、使用するメモリモデルやセグメントの方式によって、ポインタは次の3種類に分類されます。これらは主にMS-DOS時代の16ビット環境(Turbo Cなど)で使われていた概念ですが、ポインタの仕組みを理解するうえで今なお学習価値があります。
- ニアポインタ(nearポインタ)
- ファーポインタ(farポインタ)
- ヒュージポインタ(hugeポインタ)
nearポインタ(ニアポインタ)とは
nearポインタには、以下のような特徴があります。
- メモリ上の64KBのデータセグメント範囲内で動作するポインタです。
- そのデータセグメントを超えるアドレスにはアクセスできません。
- 算術演算子を使って、アドレスをインクリメント・デクリメントできます。
- キーワード
nearを付けることで、任意のポインタをnearポインタとして宣言できます。
構文
<データ型> near <ポインタ定義>;<br><データ型> near <関数定義>;
たとえば、次のように記述すると、変数sへのnearポインタが宣言されます。
char near *string;
サンプルプログラム
次のプログラムは、nearポインタの基本的な使い方を示したものです。
#include<stdio.h>
int main(void) {
int number = 50;
int near *p;
p = &number;
printf("%d", sizeof(p));
return 0;
}
実行結果
2
nearポインタは16ビット(2バイト)で表現されるため、sizeofの結果は「2」となります。
farポインタ(ファーポインタ)とは
farポインタには、以下のような特徴があります。
- 参照先のセグメントアドレスとオフセットの両方を保持するポインタです。
- すべての16個のセグメント(全メモリ領域)にアクセスできます。
- 扱えるアドレス範囲は0〜1MBです。
- ポインタをインクリメント・デクリメントしても、変化するのはオフセット部分のみで、セグメント部分は更新されません。
構文
<データ型> far <ポインタ定義>;<br><データ型> far <関数定義>;
たとえば、次のように記述すると、変数sへのfarポインタが宣言されます。
char far *s;
サンプルプログラム
次のプログラムは、farポインタの基本的な使い方を示したものです。
#include<stdio.h>
int main(void) {
int number = 50;
int far *p;
p = &number;
printf("%d", sizeof(p));
return 0;
}
実行結果
4
farポインタは32ビット(4バイト)で表現されるため、sizeofの結果は「4」となります。
hugeポインタ(ヒュージポインタ)とは
hugeポインタには、以下のような特徴があります。
- サイズの点ではfarポインタと似ており、どちらも32ビットのアドレスで表現されます。
- farポインタの弱点である「セグメントのラップアラウンド(桁あふれによる巻き戻り)」の問題を回避しながら、アドレスをインクリメントできます。
farポインタはオフセット部分だけが変化するため、オフセットが上限を超えると同じセグメント内に折り返されてしまうという欠点がありました。一方、hugeポインタはアドレス計算の際にセグメント部分も適切に更新(正規化)するため、1MBの全メモリ空間を連続的に扱うことができます。
サンプルプログラム
次のプログラムは、hugeポインタの基本的な使い方を示したものです。
#include<stdio.h>
int main(void) {
char huge *far *ptr;
printf("%d %d %d", sizeof(ptr), sizeof(*ptr), sizeof(**ptr));
return 0;
}
実行結果
4 4 1
この結果から、ptr自体(farポインタ)は4バイト、その指し示す先であるhugeポインタも4バイト、さらにその先にあるchar型データは1バイトであることがわかります。
3つのポインタの比較まとめ
| 項目 | nearポインタ | farポインタ | hugeポインタ |
|---|---|---|---|
| サイズ | 16ビット(2バイト) | 32ビット(4バイト) | 32ビット(4バイト) |
| アクセス範囲 | 64KBのセグメント内 | 0〜1MB | 0〜1MB |
| セグメント管理 | 不要 | オフセットのみ変化 | 正規化して自動更新 |
| アクセス速度 | 高速 | 中程度 | 低速 |
注意点
near、far、hugeはC言語の標準規格には含まれていないキーワードであり、Turbo CなどMS-DOS時代のコンパイラ固有の拡張です。現代の32ビット/64ビット環境ではこうした区別は存在せず、すべてのポインタがフラットなアドレス空間を扱います。本記事は、歴史的な背景やメモリモデルの仕組みを学ぶ際の参考としてご活用ください。
-
C言語におけるユニオンとポインタの使い方を徹底解説
ユニオン(共用体)とは、異なるデータ型を持つ複数の変数が、同一のメモリ領域を共有するための仕組みです。構造体が各メンバーごとに独立したメモリを割り当てるのに対し、ユニオンではすべてのメンバーが同じアドレスを参照するという点が大きな特徴です。 ユニオンの構文 ユニオンを定義するときの基本的な書式は次の通りです。 union タグ名{ データ型 メンバー1; データ型 メンバー2; ---- ---- データ型 メンバーn; }; 実際の記述例を見てみましょう。 union sample{ int a; float b; char
-
C言語のポインタ入門!宣言・初期化から配列アクセスの実例まで徹底解説
ポインタ(pointer)とは、他の変数のメモリアドレスを格納するための変数です。C言語においてポインタは、メモリを直接操作したり、関数間でデータを効率的にやり取りしたりするために欠かせない重要な概念です。 ポインタの宣言・初期化とアクセス まず、次のような通常の整数変数の宣言を見てみましょう。 int qty = 179; 変数qtyには値「179」が格納されると同時に、メモリ上のどこかにその格納場所(アドレス)が割り当てられます。 ポインタの宣言 int *p; 「p」はポインタ変数であり、別の整数型(int)変数のアドレスを保持します。変数名の前にアスタリスク(*)を付けることで、「こ