FreeBASIC マニュアルのトップに戻る

FreeBASIC ポインタの紹介

目次→教本→いっしょに学ぼうIntroduction to Pointers←オリジナル・サイト

ポインタの紹介 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

     外部参考:
       誰もがつまずくポインタを完璧理解
       C 言語にポインタがある理由は省メモリ化・高速化・開発作業の省力化です
       ポインタのメリットと必要性


ポインタとは何ですか?

ポインターは、記憶域へのアドレスを保存する、4バイトのデータ型(32ビットのシステム)または8バイトのデータ型(64ビットのシステム)です。
ポインタはデータを収納していません。ポインタは、初期化されると、データを指し示します。
初期化していないポインタは、何も指し示さなくて、未定義です。

ポインタを理解するのに、玉子のパック、それぞれの「穴」(卵を置くところ)の底に、No.1〜12 を印刷した鶏卵ケースを考えてください。
これらの穴はコンピュータの記憶域に似ています。
各穴、または記憶域には、アドレスがあります。この例では、1〜12 です。
卵が、データの項目を表すなら、穴1の卵は、1のアドレスを持っていることになります。

通常は、変数を使って、データに直接アクセスします。
ある型の変数を Dim(DIMension) するとき、データのために、保存スペースを設定しています。
このとき、データがどこにあるかを、知ったり気にかけたりする必要はありません。変数を通して、直接データにアクセスできるからです。
これは、穴の下部に書かれた数を見ずに、穴 1 で、卵を見つけて、卵をつかむことと似ています(データを読む)。
あるいは、穴1に卵を入れることに似ています(データを保存)。

ポインタを使うのは、少し異なっています。
ポインタを表す紙の切れ端があると想像してください。 今、それは、空白で、何も示しません。
ポインタが初期化されるまで、この未定義のポインタは、使えません。
ポインタを初期化するには、ポインタに、1 を書きます。
今、ポインタは、鶏卵ケースの穴 1 を「指しています」。
データ(卵)を、穴 1 に入れるために、紙の切れ端を見て、穴 1 にそれを合わせて、卵を、この穴に置きます。
卵を検索するために、私たちはまさしく正反対をします。
メモ用紙を、穴 1 に合わせて、次に、卵をつかみます。
卵を、置くこと、得ることの全ては、メモ用紙を通して行われなければなりません。これは、ポインタに「反-参照をつけ」ると呼ばれます。
つまり、ポインター (No.1) に含まれている参照アドレスを介して、データを取得します。
ポインターは、データを含んでいません。 ポインターは、データへの参照アドレスを含んでいます。

FreeBasic では、DimPtr 命令文を使ってポインタを定義します:
Dim aptr As Integer Ptr


この命令文は、上の例で、私たちの空白の紙に一致しています。
ポインタは、何も示さないで、未定義です。
今、ここで、ポインタを使おうとすると、プログラムはダウンするでしょう。

ポインタを使えるように、ポインタを初期化しなければなりません:
Dim aptr As Integer Ptr

aptr = Allocate (SizeOf(Integer))


ここで、Allocate を使って、Integer のために、メモリに、別の十分なスペースを設定します。そして、そのスペースのアドレスを、aptr に登録します。
sizeof マクロは、渡されたデータ型の、バイトで表現されるサイズを、返します。
Sizeof の代わりに len を使うこともできます。(.13b 以降)

いったんポインタを初期化すると、ポインタを使えるようになります:

* aptr = 5
Print "aptr: "; *aptr     '演算子* を使うと、ポインターが指すメモリー位置に格納されている実際の値にアクセスできます。


aptr の前の * 接頭語に注意してください。 * は、間接参照演算子です。
これは、メモ用紙上の数を、鶏卵ケースの穴の数に、突き合わせることに、似ています。
* 演算子 を使うことで、aptr が指し示す穴に含まれるデータ(卵)に達することができます。

下は、完全なプログラム例です:
'Option Explicit

Dim aptr As Integer Ptr

aptr = Allocate (SizeOf(Integer))
*aptr = 5
Print "aptr: "; *aptr
Deallocate aptr
Sleep


deallocate 関数は、aptr によって指し示されたメモリを解放します。そして、aptr はもう一度未定義になります。
これは、私たちのメモ用紙の上で、数を消しているようです。
もし、aptr を、割り当て解除した後に使うと、プログラムはダウンします。


ポインタを使うと何がよいのか?

FreeBasic にポインタを加える主な理由は、多くの外部ライブラリが、型構成へのポインタと、文字列へのポインタを必要とすることです。
例えば、Win32 API には、ポインタを通して、書き込んで、そして関数に渡さなければならない、多くの構造があります。

ポインタの別の使い方は、 の定義です。
FreeBasic の 定義は、固定長文字列を含むことができるだけです。しかし、プログラムが動くまで文字列の長さを知らないと、どうなるでしょうか?
ポインタは、この目的に役立ちます。

(型定義は、現在、可変長文字列をサポートできます。)

'Option Explicit

Type mytptr                 'ポインタを使うにはデータ型を宣言する必要があります。
    sptr As ZString Ptr     'Pointer か Ptr を使ってポインタ変数を宣言します。
End Type

'この関数は、渡された文字列のために、スペースを割り当てます
'そして、それを記憶域にロードします。そして、
'文字列へのポインタを返します
Declare Function pSetString(ByVal s As String) As ZString Ptr

'型の変数
Dim mytype As mytptr

'型定義に、変数文字列を設定します
mytype.sptr = pSetString ("Hello World From FreeBasic!")
Print "aptr: "; *mytype.sptr
Deallocate(mytype.sptr)
Sleep
End

Function pSetString(ByVal s As String) As ZString Ptr
    Dim sz As ZString Ptr

    'chr(0) のために、スペース + 1 を割り当てます
    sz = Allocate (Len(s) + 1)
    '文字列を記憶域に登録します
    *sz = s
    'ポインタを戻します
    Return sz
End Function


ここでは、項目 sptr で、型を、zstring ptr と定義します。
Zstrings は、ヌル終わる文字列で、多くの外部のライブラリによって使われます。そして、動的割当てのために設計されています。
型を定義した後、dim 命令文で型のインスタンスを作成します:

Dim mytype As mytptr


そして、 定義で欲しい、可変長文字列のアドレスを得るために、関数 pSetString を呼びます。

mytype.sptr = pSetString ("Hello World From FreeBasic!")


sptr はポインタとして定義されていて、文字列変数ではないことを、覚えておいて下さい。このため、pSetStringは、文字列自体ではなく、文字列へのポインタ(メモリ・アドレス)を返します。
言い換えれば、文字列が、穴 #1 にあるなら、pSetString は、1 を返します。

関数 pSetString は、一時的な zstring sz を、使って、渡された文字列パラメータ s のために、スペースを 割り当て ます。
zstring は、ヌルで終わる文字列なので、関数を 割り当てる ときに、ヌル終端文字列(null terminator)のために、s の長さに 1 を加えなければなりません。

'chr(0) のために、スペース + 1 を割り当てます
sz = Allocate (Len(s) + 1)


文字列にいったんスペースを割り当てると、間接参照演算子 * を使って、データを記憶域にロードします。

'文字列を記憶域に読み込みます
*sz = s


そして、ポインタ(文字列のアドレス)を、型に戻します。型は、mytype.sptr に、保存されます。

'ポインタを返します
Return sz


今、間接参照演算子を使って、型の中の文字列を、間接参照できます。

Print "aptr: "; *mytype.sptr


ポインタは、初心者には分かりにくいかもしれません。ポインターがデータを含んでいないことを心にとめておけば、混乱することはありません。ポインターは、何かデータを指すだけです。
ポインタはメモリアドレスです。そして、間接参照演算子 * を通してそのデータを操ります。ポインタは、普通の変数と、あまり変わりはありません。

sancho3 が、2018年2月7日に修正しました。

参照:
いっしょに学ぼう に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2018-08-16 14:56:21
日本語翻訳:WATANABE Makoto、原文著作者:WikiRick(Rick Clark aka rdc)

ホームページのトップに戻る

表示-非営利-継承