OpenVMS
HP C ランタイム・ライブラリ・
リファレンス・マニュアル (上巻)


前へ 次へ 目次 索引


1.10.1 HP C ランタイム・ライブラリの使用

OpenVMS Alpha バージョン 7.0 以降のシステムでは, HP C ランタイム・ライブラリは 64 ビット・ポインタを生成したり,受け付けることができます。 64 ビット・ポインタで使用される第 2 のインタフェースを必要とする関数は,対応する 32 ビットの関数と同じオブジェクト・ライブラリおよび共用可能イメージに存在します。新しいオブジェクト・ライブラリや共用可能イメージが提供されるわけではありません。 64 ビット・ポインタを使用する場合,リンク・コマンドやリンク・オプション・ファイルを変更する必要はありません。

HP C の 64 ビット環境では,アプリケーションは 32 ビット・アドレスと 64 ビット・アドレスの両方を使用できます。ポインタ・サイズの操作方法の詳細については,『HP C User's Guide for OpenVMS Systems』の /POINTER_SIZE 修飾子と, #pragma pointer_sizeおよび #pragma required_pointer_sizeプリプロセッサ・ディレクティブを参照してください。

/POINTER_SIZE 修飾子には,32 または 64 の値を指定する必要があります。この値は,コンパイル・ユニットの内部でデフォルト・ポインタ・サイズとして使用されます。32 ビット・ポインタを使用して 1 組のモジュールをコンパイルし,64 ビット・ポインタを使用して別の 1 組のモジュールをコンパイルすることができます。これらの 2 組のモジュールを相互に呼び出す場合は,注意を払う必要があります。

/POINTER_SIZE 修飾子の使用は, HP C RTL ヘッダ・ファイルの処理にも影響を与えます。 32 ビット・インプリメンテーションと 64 ビット・インプリメンテーションの両方がある関数の場合, /POINTER_SIZE を指定すると,修飾子に指定された実際の値とは無関係に,関数プロトタイプは両方の関数にアクセスできます。さらに,修飾子に指定された値によって,そのコンパイル・ユニットで呼び出すデフォルトのインプリメンテーションが決定されます。

#pragma pointer_sizeおよび #pragma required_pointer_sizeプリプロセッサ・ディレクティブを使用すると,コンパイル・ユニットの内部で有効なポインタ・サイズを変更することができます。デフォルトのポインタ・サイズを 32 ビット・ポインタに設定した後,モジュール内で特定のポインタを 64 ビット・ポインタとして宣言することができます。また,64 ビット・メモリ領域からメモリを取得するには, malloc_malloc64という形式を特別に呼び出す必要もあります。

1.10.2 メモリへの 64 ビット・ポインタの取得

HP C RTL には,新たに割り当てられたメモリへのポインタを返す関数が数多くあります。これらの各関数では,アプリケーションはポインタによって示されるメモリを所有し,そのメモリを解放する責任があります。

メモリを割り当てる関数は次のとおりです。

malloc
calloc
realloc
strdup

これらの各関数には,32 ビット・インプリメンテーションと 64 ビット・インプリメンテーションがあります。 /POINTER_SIZE 修飾子を使用すると,次の関数も呼び出すことができます。

_malloc32_malloc64
_calloc32_calloc64
_realloc32_realloc64
_strdup32_strdup64

/POINTER_SIZE=32 を指定した場合,すべての mallocの呼び出しはデフォルトで _malloc32に設定されます。

/POINTER_SIZE=64 を指定した場合,すべての mallocの呼び出しはデフォルトで _malloc64に設定されます。

アプリケーションで 32 ビットのメモリ割り当てルーチンを呼び出す場合も, 64 ビットのメモリ割り当てルーチンを呼び出す場合も, free関数は 1 つしかありません。この関数はどちらのポインタ・サイズも受け付けます。

64 ビット・メモリを指すポインタを返すのは,メモリ割り当て関数だけであるということに注意しなければなりません。呼び出し元のアプリケーションに返されるすべての HP C RTL 構造体ポインタ (FILE,WINDOW,DIR など ) は常に 32 ビット・ポインタです。このため,32 ビットと 64 ビットの両方の呼び出し元アプリケーションがこれらの構造体ポインタをアプリケーションの内部で渡すことができます。

1.10.3 HP C ヘッダ・ファイル

バージョン 5.2 以降の C コンパイラで配布されるヘッダ・ファイルでは, 64 ビット・ポインタがサポートされます。シグネチャにポインタが含まれる各関数プロトタイプは,受け付けるポインタのサイズを示すように作成されています。

32 ビット・ポインタは,引数として 32 ビットまたは 64 ビットのポインタを受け付ける関数に対して,引数として渡すことができます。

しかし,32 ビット・ポインタを受け付ける関数に対する引数として, 64 ビット・ポインタを渡すことはできません。このような処理はコンパイラで診断され,MAYLOSEDATA メッセージが出力されます。診断メッセージ IMPLICITFUNC は,コンパイラがその関数の呼び出しでポインタ・サイズの追加確認を実行できないことを示します。この関数が HP C RTL 関数の場合は,その関数を定義しているヘッダ・ファイルの名前については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』「リファンレンス・セクション」を参照してください。

ポインタ・サイズに関する次のコンパイラ診断情報は役立ちます。

1.10.4 影響を受ける関数

OpenVMS Alpha バージョン 7.0 に添付されている HP C RTL は,32 ビット・ポインタのみ, 64 ビット・ポインタのみ,またはその両方の組み合わせを使用するアプリケーションに対応します。 64 ビット・メモリを使用するには,少なくともアプリケーションの再コンパイルと再リンクが必要です。必要なソース・コードの変更の量は,アプリケーション自体,他のランタイム・ライブラリの呼び出し,使用するポインタ・サイズの組み合わせに応じて異なります。

64 ビット・ポインタのサポートに関して, HP C RTL 関数は次の 4 種類に分類できます。

アプリケーション開発者の立場から考えると,最初の 2 種類の関数は単一ポインタ・モードまたは複合ポインタ・モードで最も簡単に使用できます。

3 番目の関数は, 1 種類のポインタだけを使用してコンパイルする場合は変更が不要ですが,複合ポインタ・モードで使用する場合はソース・コードの変更が必要です。

4 番目の関数は, 64 ビット・ポインタを使用しなければならないときに注意する必要があります。

1.10.4.1 ポインタ・サイズの影響を受けない関数

プロトタイプにポインタ関連パラメータや戻り値が含まれていない場合は,ポインタ・サイズの選択は関数に影響を与えません。このような関数の例として,算術演算関数があります。

このカテゴリに分類される関数で,プロトタイプにポインタを含む一部の関数もポインタ・サイズの影響を受けません。たとえば, strerrorには,次のプロトタイプがあります。


char * strerror (int error_number); 

この関数は文字列を指すポインタを返しますが,この文字列は HP C RTL によって割り振られます。この結果,32 ビット・アプリケーションと 64 ビット・アプリケーションの両方をサポートするために,これらのポインタ・タイプは 32 ビット・ポインタに収まるように保証されます。

1.10.4.2 両方のポインタ・サイズを受け付ける関数

Alpha アーキテクチャでは 64 ビット・ポインタがサポートされます。 OpenVMS Alpha の呼び出し標準規約では,すべての引数は実際に 64 ビットの値として渡されることが指定されています。 OpenVMS Alpha バージョン 7.0 より前のバージョンでは,プロシージャに渡されるすべての 32 ビット・アドレスは,この 64 ビット・パラメータになるように符号拡張されていました。呼び出される関数は 32 ビット・アドレスとしてパラメータを宣言し,コンパイラはこれらのパラメータを操作するために 32 ビットの命令 (LDL など) を生成していました。

HP C RTL の多くの関数は,完全な 64 ビット・アドレスを受け付けることができるように拡張されています。たとえば, strlenについて考えてみましょう。


size_t strlen (const char *string); 

この関数のポインタは文字列ポインタだけです。呼び出し元が 32 ビット・ポインタを渡すと,関数は符号拡張された 64 ビット・アドレスを操作します。呼び出し元が 64 ビット・アドレスを渡した場合は,関数はそのアドレスを直接操作します。

HP C RTL は,このカテゴリに分類される関数に対して,今後もエントリ・ポイントを 1 つだけ使用します。この種の関数に対して 4 種類のポインタ・サイズ・オプションを追加するためにソース・コードを変更する必要はありません。 OpenVMS のドキュメントでは,このような関数を「64 ビットと親和性がある関数」と呼んでいます。

1.10.4.3 2 つのインプリメンテーションのある関数

多くの理由から,1 つの関数に対して 32 ビット・ポインタを取り扱うインプリメンテーションと 64 ビット・ポインタを取り扱うインプリメンテーションを用意しなければならないことがあります。たとえば,次のような場合が考えられます。

アプリケーション開発者の立場から考えると,これらの各関数に対して 3 つの関数プロトタイプがあります。 <string.h>ヘッダ・ファイルには,戻り値が関数呼び出しの最初の引数として使用されたポインタ・サイズに依存する多くの関数が含まれています。たとえば, memset関数について考えてみましょう。ヘッダ・ファイルはこの関数に対して 3 つのエントリ・ポイントを定義しています。


void * memset   (void *memory_pointer, int character, size_t size); 
void *_memset32 (void *memory_pointer, int character, size_t size); 
void *_memset64 (void *memory_pointer, int character, size_t size); 

最初のプロトタイプは,この関数を使用したときにアプリケーションが現在呼び出している関数です。 /POINTER_SIZE=32 を使用してコンパイルした場合は,コンパイラは memsetに対する呼び出しを _memset32に変更し, /POINTER_SIZE=64 を指定してコンパイルした場合は, _memset64に変更します。

このデフォルトの動作は,関数の 32 ビット形式または 64 ビット形式を直接呼び出すことにより変更できます。この機能は,/POINTER_SIZE 修飾子で指定したデフォルト・ポインタ・サイズとは無関係に,複合ポインタ・サイズを使用するアプリケーションに対応します。

/POINTER_SIZE 修飾子を指定せずにアプリケーションをコンパイルした場合は,32 ビット固有の関数プロトタイプも, 64 ビット固有の関数プロトタイプも定義されません。この場合,コンパイラは 2 種類のインプリメンテーションのあるすべてのインタフェースに対して,自動的に 32 ビット・インタフェースを呼び出します。

表 1-6 は,64 ビット・ポインタ・サイズをサポートするために 2 種類のインプリメンテーションを用意している HP C RTL 関数を示しています。 /POINTER_SIZE 修飾子を使用してコンパイルした場合,変更されていない関数名の呼び出しは,修飾子に指定したポインタ・サイズに対応する関数インタフェースに変更されます。

表 1-6 2 種類のインプリメンテーションが用意されている関数
basename bsearch calloc catgets
ctermid cuserid dirname fgetname
fgets fgetws gcvt getcwd
getname getpwent getpwnam getpwnam_r
getpwuid getpwuid_r gets index
longname malloc mbsrtowcs memccpy
memchr memcpy memmove memset
mktemp mmap qsort readv
realloc rindex strcat strchr
strcpy strdup strncat strncpy
strpbrk strptime strrchr strsep
strstr strtod strtok strtok_r
strtol strtoll strtoq strtoul
strtoull strtouq tmpnam wcscat
wcschr wcscpy wcsncat wcsncpy
wcspbrk wcsrchr wcsrtombs wcsstr
wcstok wcstol wcstoul wcswcs
wmemchr wmemcpy wmemmove wmemset
writev      

表 1-7 に, 64 ビット・ポインタ・サイズをサポートするために 2 種類のインプリメンテーションが用意されている TCP/IP ソケット・ルーチンを示します。

表 1-7 2 種類のインプリメンテーションが用意されているソケット・ルーチン
freeaddrinfo getaddrinfo
recvmsg sendmsg

注意

OpenVMS V7.3-2 で 64 ビット・ポインタ・サポートを提供する次のような関数について考えて見ましょう。


getaddrinfo        getpwnam 
freeaddrinfo       getpwuid 
sendmsg            getpwent 
recvmsg 

これらの関数は,以前はたとえ /POINTER_SIZE=LONG を指定してコンパイルしても 32 ビットのみサポートしていました。 /POINTER_SIZE=LONG でコンパイルした場合もこれらの関数で以前の 32 ビット・ポインタ・サポートの動作を保つようにするため,これらの 7 つの関数は,この項で説明する 32 ビットと 64 ビットのサポートのための通常の規則には従いません。

これらの関数の次のような変形とそれらが対応する構造体が, 64 ビット・サポートのために C RTL に追加されています。


Function                        Structure 
--------                        --------- 
__getaddrinfo32                 __addrinfo32 
__getaddrinfo64                 __addrinfo64 
__freeaddrinfo32                __addrinfo32 
__freeaddrinfo64                __addrinfo64 
__recvmsg32                     __msghdr32 
__recvmsg64                     __msghdr64 
__sendmsg32                     __msghdr32 
__sendmsg64                     __msghdr64 
__32_getpwnam                   __passwd32 
__64_getpwnam                   __passwd64 
__32_getpwuid                   __passwd32 
__64_getpwuid                   __passwd64 
__32_getpwent                   __passwd32 
__64_getpwent                   __passwd64 

これらの関数の標準バージョンをコンパイルする場合は,次のような動作が発生します。

  • /POINTER_SIZE=32 を指定すると,コンパイラは, 32 ビット・バージョンの関数呼び出しに変換します。たとえば, getaddrinfo__getaddrinfo32に変換されます。

  • /POINTER_SIZE=64 を指定すると,コンパイラは, 64 ビット・バージョンの関数呼び出しに変換します。たとえば, getaddrinfo__getaddrinfo64に変換されます。

  • /POINTER_SIZE 修飾子を指定しなかった場合, 32 ビット固有関数プロトタイプも 64 ビット固有関数プロトタイプも定義されません。


前へ 次へ 目次 索引