[ 前のページ ] [ 次のページ ] [ 目次 ] [ 索引 ] [ DOC Home ]

11 DEC C RTLの64ビット・アドレッシング・サポート

本章はOpenVMS Alphaバージョン7.0以降のDEC Cランタイム・ライブラリで提供される 64ビット・アドレッシング・サポートについて説明します。

DEC Cランタイム・ライブラリは, 64ビット・ポインタをサポートする際に以下の特徴があります。


11.1 DEC Cランタイム・ライブラリの使用

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

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

/POINTER_SIZE修飾子に対して,ユーザは値32または64を指定します。 ここで指定した値は, コンパイル・ユニットの中の省略時の設定のポインタ・サイズとして使用されます。 アプリケーション・プログラマは,あるモジュール・セットは 32ビット・ポインタを使用して,また別のセットは 64ビット・ポインタを使用してコンパイルします。この 2つのモジュール・グループがお互いを呼び出す場合,特に注意しなければなりません。

/POINTER_SIZE修飾子の使用は,DEC C RTLヘッダ・ファイルの処理にも影響します。 32ビット実装および64ビット実装を持つ関数の場合, 修飾子に指定される実際の値に関わらず,/POINTER SIZE修飾子によって関数プロトタイプは両方の関数にアクセスできます。さらに, 修飾子に指定される値は, コンパイル・ユニットの中で呼び出す省略時の設定の実装を決定します。

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


11.2 メモリを指す 64ビット・ポインタの取得

DEC 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 関数があります。 この関数はどちらのサイズのポインタも受け取ります。

メモリ割り当て関数は,64ビット・メモリへのポインタを返す唯一の関数です。 (FILE,WINDOW,DIRなどのように)呼び出しアプリケーションに返されるすべての DEC C RTL構造ポインタは,通常は32ビット・ポインタです。このため32ビットと 64ビットの両方の呼び出し側とも, アプリケーションの中でこれらの構造ポインタを渡すことができます。


11.3 DEC Cヘッダ・ファイル

DEC Cバージョン5.2以降で提供するヘッダ・ファイルは, 64ビット・ポインタをサポートします。ポインタを含む各関数プロトタイプは, 受け取るポインタのサイズを示すように構成されています。

32ビット・ポインタまたは64ビット・ポインタのいずれか 1つを引数として受け取る関数に対して, 32ビット・ポインタをその引数として渡すことができます。

しかし,32ビット・ポインタを受け取る関数への引数として, 64ビット・ポインタを渡すことはできません。この操作を試みると, コンパイラによって診断が行われ,MAYLOSEDATAメッセージが表示されます。なお, IMPLICITFUNC診断メッセージが表示された場合,これは,その関数の呼び出しについて, ポインタ・サイズのチェックをこれ以上実行できないことを表します。

特に有効なポインタ・サイズについてのコンパイラの診断メッセージを次に示します。


11.4 影響のある関数

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

DEC C RTL関数は,次の4種類に分類できます。

アプリケーション開発者の立場からすると,上記の最初の 2つの関数は単一ポインタ・モードと混合ポインタ・モードのいずれの場合も簡単に使用できます。

3番目の関数は, 単一ポインタ・モードで使用している場合はソース・コードを変更する必要はありません。 ただし混合ポインタ・モードで使用している場合は,ソース・コードの変更が必要です。

4番目の関数は,64ビット・ポインタを使用している場合は十分な注意が必要です。


11.4.1 ポインタ・サイズの影響がない関数

プロトタイプにポインタに関連するパラメータや戻り値が含まれていない場合, ポインタ・サイズの選択による関数への影響を考慮する必要はありません。 算術関数がこれに相当します。

この種類の関数のうち,プロトタイプにポインタを含まない関数は, ポインタ・サイズの選択による影響はありません。たとえば strerror 関数のプロトタイプは次のとおりです。

     char * strerror (int error_number);
この関数は文字列へのポインタを返しますが,この文字列は DEC C RTLで割り当てられます。その結果,32ビット・アプリケーションと 64ビット・アプリケーションを両方ともサポートするために,この種類のポインタは, 32ビット・ポインタに対応することが常に保証されています。


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

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

DEC C RTL内の関数の多くは拡張され, 64ビット・アドレス全体を受け取るようになりました。関数strlen を例に考えます。

     size_t strlen (const char *string);
この関数内の唯一のポインタは文字列ポインタです。ユーザが 32ビット・ポインタを渡すと,関数は符号拡張された64ビット・アドレスで動作します。 ユーザが64ビット・アドレスを渡すと,関数はそのアドレスで直接動作します。

DEC C RTLは引き続き,この種類の関数に対して, 1つのエントリ・ポイントだけを持ちます。この種類の関数の 4つのポインタ・サイズ・オプションのいずれを追加する場合も, ソース・コードの変更は必要ありません。OpenVMSマニュアルでは, これらの関数を64ビット・フレンドリと呼びます。


11.4.3 2種類の実装を持つ関数

多くの理由から,関数は,32ビット・ポインタ用と64ビット・ポインタ用に 2種類の実装を持つ必要があります。その理由を次に示します。 アプリケーション開発者の立場から見ると,これらの各関数にはそれぞれ 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);

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

関数の32ビット形式または64ビット形式を直接呼び出すことにより, この省略時の設定の動作を変更することができます。これにより /POINTER_SIZE修飾子で指定した省略時の設定のポインタ・サイズに関係なく, ポインタ・サイズが混在しているアプリケーションに対応できます。

/POINTER_SIZE修飾子を指定せずにコンパイルしている場合, 32ビット固有のインタフェース関数プロトタイプも, 64ビット固有のインタフェース関数プロトタイプも定義されないことに注意してください。 この場合コンパイラは,2種類の実装を持つインタフェースに対して,自動的に 32ビット・インタフェースを呼び出します。

DEC C RTLでの64ビット・ポインタ・サイズのサポートの一環として, 2種類の実装を持つ関数の一覧を 表 11-1に示します。 /POINTER_SIZE修飾子を指定してコンパイルしている場合, 修正されていない関数名を呼び出すと, その修飾子で指定されるポインタ・サイズに対応するインタフェースが呼び出されます。

表 11-1 2種類の実装を持つ関数

basename malloc strpbrk wcsncat
bsearch mbsrtowcs strptime wcsncpy
calloc memccpy strrchr wcspbrk
catgets memchr strsep wcsrchr
ctermid memcpy strstr wcsrtombs
cuserid memmove strtod wcsstr
dirname memset strtok wcstok
fgetname mktemp strtol wcstol
fgets mmap strtoll wcstoul
fgetws qsort strtoq wcswcs
fullname realloc strtoul wmemchr
gcvt rindex strtoull wmemcpy
getcap strcat strtouq wmemmove
getcwd strchr tgetstr wmemset
getname strcpy tmpnam
gets strdup wcscat
index strncat wcschr
longname strncpy wcscpy


11.4.4 32ビット・ポインタに制限されている関数

DEC C RTLには64ビット・ポインタをサポートしない関数もあります。 64ビット・ポインタをサポートしない関数に64ビット・ポインタを渡そうとすると, コンパイラは%CC-W-MAYLOSEDATA警告メッセージを生成します。 /POINTER_SIZE=64修飾子を指定してコンパイルしたアプリケーションは, 64ビット・ポインタをサポートしない関数に 64ビット・ポインタを渡すことがないように, ソース・コードの修正が必要な場合があります。

32ビット・ポインタしか使用できない関数を 表 11-2に示します。 DEC C RTLは,これらの関数に対して64ビット・サポートを提供していません。

表 11-2 32 ビット・ポインタに制限されている関数

atexit getopt modf setstate
execve iconv recvmsg setvbuf
execvp initstate sendmsg
frexp ioctl setbuf

関数呼び出し処理の一部として, ユーザが提供する関数へのコールバックを行う関数の一覧を 表 11-3に示します。 コールバック・プロシージャに64ビット・ポインタが渡されることはありません。

表 11-3 32ビット・ポインタだけを渡すコールバック

from_vms to_vms
ftw tputs


11.5 ヘッダ・ファイルの読み込み

この節では,DEC C RTLヘッダ・ファイルで使用されるポインタ・サイズ操作について説明します。 次の例を参考にヘッダ・ファイルを読み, 必要に応じてヘッダ・ファイルを修正してください。

  1. :
    #if INITIAL__POINTER_SIZE 【1】
    #   if (VMS__VER < 70000000) || !defined __ALPHA 【2】
    #      error " Pointer size usage not permitted before OpenVMS Alpha V7.0"
    #   endif
    #   pragma __pointer_size __save 【3】
    #   pragma __pointer_size 32 【4】
    #endif
    :
    :
    #if __INITIAL_POINTER__SIZE 【5】
    #   pragma __pointer_size 64
    #endif
    :
    :
    #if __INITIAL_POINTER_SIZE 【6】
    #   pragma __pointer_size __restore
    #endif
    :
    
    
    /POINTER_SIZE修飾子をサポートするすべてのDEC Cコンパイラは,あらかじめマクロ __INITIAL_POINTER_SIZE を定義しています。 このマクロが定義されていない場合,DEC C RTLヘッダ・ファイルは, 暗黙値0を使用するというANSI規則を利用します。

    /POINTER_SIZE修飾子が使用される場合,マクロは32または64として定義されます。 この修飾子が使用されない場合は,0として定義されます。 【1】の文は, "ユーザがコマンド・ラインで/POINTER_SIZE=32 または/POINTER_SIZE=64 を指定した場合"という意味です。

    DEC Cバージョン5.2以降は,多くのOpenVMSプラットフォームでサポートされます。 コンパイルのターゲットが64ビット・ポインタをサポートしない場合, 【2】の行はエラー・メッセージを生成します。

    ヘッダ・ファイルは,このヘッダがインクルードされる時点では, 作用する実際のポインタ・サイズ・コンテキストを決定することができません。 さらに,DEC Cコンパイラは,__INITIAL_POINTER_SIZE マクロと, ポインタ・サイズを変更するメカニズムだけを提供し, 現在のポインタ・サイズを決定することはしません。

    ポインタ・サイズに依存するヘッダ・ファイルはすべて,ポインタ・サイズ・コンテ キストの保存【3】,初期化【4】,変更【5】,および復元【6】を行う必要があります。

  2. :
    #ifndef __CHAR_PTR32 【1】
    #   define __CHAR_PTR32 1
        typedef char * __char_ptr32;
        typedef const char * __const_char_ptr32;
    #endif
    :
    :
    #if __INITIAL_POINTER__SIZE
    #   pragma __pointer_size 64
    #endif
    :
    :
    #ifndef __CHAR_PTR64 【2】
    #   define __CHAR_PTR64 1
        typedef char *__ char_ptr64;
        typedef const char * __const_char_ptr64;
    #endif
    :
    
    
    64ビット・ポインタ・サイズ・コンテキストの中で, 32ビット・ポインタを参照する必要がある関数プロトタイプがあります。また, 32ビット・ポインタ・サイズ・コンテキストの中で, 64ビット・ポインタを参照する必要がある関数プロトタイプもあります。

    DEC Cコンパイラは,typedef が作成される時点で, typedef で使用されるポインタ・サイズを結合させます。 __char_ptr32typedef 宣言【1】は 32ビット・コンテキストで行われます。 __char_ptr64typedef 宣言【2】は64ビット・コンテキストで行われます。

  3. :
    #if INITIAL__POINTER_SIZE
    #   if (__VMS_VER < 70000000) || !defined __ALPHA
    #      error " Pointer size usage not permitted before OpenVMS Alpha V7.0"
    #   endif
    #   pragma __pointer_size save
    #   pragma __pointer_size 32
    #endif
    :
    【1】
    :
    #if __INITIAL_POINTER_SIZE 【2】
    #   pragma __pointer_size 64
    #endif
    :
    【3】
    :
    int abs (int __j);【4】
    :
    __char_ptr32 strerror (int __errnum);【5】
    :
    
    
    64ビット・ポインタをサポートする関数プロトタイプの宣言の前に, ポインタ・コンテキストが32ビット・ポインタから 64ビット・ポインタに変更されています【2】。

    32ビット・ポインタに制限されている関数は,ヘッダ・ファイルの 32ビット・ポインタ・コンテキスト・セクション【1】に配置されています。 ほかの関数はすべて,ヘッダ・ファイルの 64ビット・ポインタ・コンテキスト・セクション【2】に配置されています。

    ポインタ・サイズの影響を受けない関数(【4】および【5】)は, 64ビット・セクションに配置されています。これらの関数は 32ビット・アドレスの戻り値を除き,ポインタ・サイズの影響は受けません【5】。 またこれらの関数は64ビット・セクションにあり,前述の32ビット固有の typedefを使用します。

  4. :
    #if __INITIAL_POINTER_SIZE
    #   pragma __pointer_size 64
    #endif
    :
    :
    #if __INITIAL_POINTER_SIZE == 32 【1】
    #   pragma __pointer_size 32
    #endif
    :
    char *strcat (char *__s1, __const_char_ptr64 __s2); 【2】
    :
    #if __INITIAL_POINTER_SIZE
    #   pragma __pointer_size 32
        :
        char *_strcat32  (char *__s1, __const_char_ptr64 __s2); 【3】
        :
    #   pragma __pointer_size 64
        :
        char *_strcat64  (char *__s1, const char *__s2); 【4】
        :
    #endif
    :
    
    
    この例は,32ビット実装と64ビット実装の両方を持つ関数に対する宣言です。 これらの宣言は,ヘッダ・ファイルの64ビット・セクションに配置されています。

    関数の通常の宣言【2】は, /POINTER_SIZE修飾子で指定したポインタ・サイズを使用して行われます。 ヘッダ・ファイルが64ビット・ポインタ・コンテキストにあり, 【1】に文を指定しているため,【2】の宣言は /POINTER_SIZE修飾子と同じポインタ・サイズ・コンテキストを使用して行われます。

    32ビット固有のインタフェース【3】および 64ビット固有のインタフェース【4】は, 32ビット・ポインタ・サイズ・コンテキストおよび 64ビット・ポインタ・サイズ・コンテキストの中でそれぞれ宣言されています。


[ 前のページ ] [ 次のページ ] [ 目次 ] [ 索引 ] [ DOC Home ]