日本-日本語
日本HPホーム 製品 & サービス OpenVMS製品情報
≫  お問い合わせ


OpenVMS マニュアル


 

OpenVMS ドキュメント
ライブラリ

タイトルページ
目次
まえがき
第 1 章:はじめに
第 2 章:入出力について
第 3 章:文字/文字列/引数リスト関数
第 4 章:エラー処理とシグナル処理
第 5 章:サブプロセス関数
第 6 章:Curses画面管理関数とマクロ
第 7 章:算術関数
第 8 章:メモリ割り当て関数
第 9 章:システム関数
第 10 章:国際化ソフトウェアの開発
第 11 章:日付/時刻関数
第 12 章:シンボリックリンクとPOSIXパス名
付録 A:各OSバージョンでサポートする関数一覧
付録 B:非標準ヘッダに複製されているプロトタイプ
索引
PDF
OpenVMS ホーム

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


目次 索引

レコード出力エミュレーションの最初の部分は,論理レコードの作成です。データ・バイトをレコード・ファイルに書き込む場合,エミュレータは書き込む情報からレコード境界を調べます。バイト・ストリームでの情報の処理は,次に示すように,出力先のファイルやデバイスの属性に応じて異なります。

  • どのファイルの場合も,出力されるバイト数が HP C RTL で割り振られた内部バッファより大きい場合は,レコードが出力されます。

  • 固定長レコード (RFM = FIX) のファイルや, "ctx=bin" または "ctx=xplct" を指定してオープンされたファイルの場合は,レコードは内部バッファが満杯になるか,または flush関数が呼び出された場合にだけ出力されます。

  • STREAM_CR レコード・フォーマット (RFM = STMCR) のファイルの場合は, HP C RTL は,キャリッジ・リターン文字 (\r) を検出したときにレコードを出力します。

  • STREAM レコード・フォーマット (RFM = STM) のファイルの場合は, HP C RTL は改行 (\n),改ページ (\f),垂直タブ (\v) 文字を検出したときにレコードを出力します。

  • 他のすべてのファイル・タイプの場合, HP C RTL は改行文字 (\n) を検出したときにレコードを出力します。

レコード出力エミュレーションの 2 番目の部分では,最初のステップで作成した論理レコードを書き込みます。 HP C RTL は出力レコードを次のように作成します。

  • レコード属性がキャリッジ制御 (R AT = CR) で,論理レコードが改行文字 (\n) で終了する場合は, HP C RTL は改行文字を削除し,暗黙のキャリッジ制御を付けて論理レコードを書き込みます。

  • レコード属性がプリント・キャリッジ制御 (RAT = PRN) の場合は, HP C RTL は RMS で指定されている規則に従ってプリント・キャリッジ制御を付けてレコードに書き込みます。論理レコードが 1 文字の改行文字 (\n) で終了する場合は,改行文字を x01 接頭文字および x8D 接尾文字に変換します。これは,プリント・キャリッジ制御属性の付いたレコード・ファイルを入力する場合と逆の変換です。

  • レコード属性が Fortran キャリッジ制御 (RAT = FTN) の場合は, HP C RTL は先頭および末尾のキャリッジ制御文字を削除し, RMS の定義に従ってレコードの先頭に 1 バイトのキャリッジ制御バイトを付加します。ただし,1 つの例外があります。出力レコードが改行文字 (\n) で終了する場合は, HP C RTL は改行文字を削除し,スペース・キャリッジ制御バイトを使用します。これは,Fortran キャリッジ制御属性を持つレコード・ファイルを入力する場合の逆の変換です。
    Fortran キャリッジ制御の変換は, "ctx=nocvt" を使用することで無効に設定することができます。

  • 論理レコードが端末デバイスに書き込まれ,レコードの最後の文字が改行文字 (\n) の場合は, HP C RTL は改行文字をキャリッジ・リターン (\r) に置き換え,レコードの先頭に改行文字 (\n) を付加します。その後, HP C RTL はキャリッジ制御を付けずにレコードを書き込みます。

  • 出力されるファイル・レコード・フォーマットが固定長制御部付可変長 (RFM = VFC) で,レコード属性にプリント・キャリッジ制御が含まれてない (RAT が PRN でない) 場合は, HP C RTL は論理レコードの先頭を固定長制御ヘッダとして解釈し,書き込むバイト数をヘッダの長さだけ少なくします。これらのバイトは固定長制御ヘッダを作成するために使用されます。論理レコードのバイト数が少なすぎる場合はエラーが報告されます。

1.7.2.2.1 レコード・モードでの可変長または VFC レコード・ファイルへのアクセス

レコード・モードで可変長または VFC レコード・ファイルにアクセスする場合,多くの I/O 関数がストリーム・モードの場合と異なる動作をします。ここでは,これらの相違点について説明します。

一般に,どのレコード・モードでも改行文字 (\n) がレコード区切り文字として使用されます。出力時には,改行文字が検出されると,改行の解釈に影響を与える省略可能な引数 (たとえば "ctx=bin" や "ctx=xplct" など) を指定していない限り,レコードが作成されます。

read関数と decc$record_read関数は常に最大 1 つのレコードを読み込みます。 write関数と decc$record_write関数は常に少なくとも 1 つのレコードを作成します。

decc$record_read関数は read関数に対応し, decc$record_write関数は write関数に対応します。ただし,これらの関数はファイル記述子ではなく,ファイル・ポインタを操作する点が異なります。

read関数は最大 1 つのレコードを読み込みますが, fread関数では複数のレコードにわたる読み込みが可能です。 fread関数は,number_items によって指定される数のレコードを読み込むのではなく (number_itemsfreadの 3 番目のパラメータ), number_items x size_of_item に等しいバイト数を読み込もうとします (size_of_itemfreadの 2 番目のパラメータ)。 freadから返される値は,読み込んだバイト数を size_of_item で除算した値に等しくなります。

fwrite関数は常に少なくとも number_items で指定される数のレコードを作成します。

fgets関数と gets関数は改行文字またはレコード境界まで読み込みます。

バッファに書き込まなければならないデータがある場合, fflush関数は常にレコードを生成します。 closefclosefseeklseekrewindfsetposの場合も同様で,これらの関数はすべて,暗黙に fflush関数を実行します。

最大レコード・サイズに指定されている文字より多くの文字を書き込もうとした場合も,レコードが生成されます。

これらの関数の詳細については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』「リファレンス・セクション」を参照してください。

1.7.2.2.2 レコード・モードでの固定長レコード・ファイルへのアクセス

レコード・モードで固定長レコード・ファイルにアクセスする場合, I/O 関数は一般に, 第 1.7.2.2.1 項 で説明したように動作します。

省略可能な引数 "ctx=xplct" を指定してファイルをオープンした場合を除き,指定したレコード・サイズが最大レコード・サイズの整数倍でないと, write関数, fwrite関数, decc$record_write関数はエラーになります。他のすべての出力関数は n バイトごとにレコードを生成します。ただし,n は最大レコード・サイズです。

fflushによって新しいレコードが生成される場合,最大レコード・サイズになるようにバッファ内のデータにヌル文字が付加されます。

  注意
ファイルの終端 (EOF) を検索するプログラムの場合,このヌル文字の付加が問題になることがあります。たとえば,プログラムでファイルの終端にデータを追加した後,ファイルを逆向きにシークし ( fflushが実行されます),その後で再びファイルの終端を検索すると,元のファイルの終端がレコード境界上になかった場合,元のファイルの終端と新しいファイルの終端の間に, 0 が埋め込まれた「穴」が作成されています。



例 1-1 は,ストリーム・モードとレコード・モードのアクセスの相違点を示しています。

例 1-1 ストリーム・モードとレコード・モードのアクセスの相違点
/*      CHAP_1_STREAM_RECORD.C                       */ 
 
/* This program demonstrates the difference between  */ 
/* record mode and stream mode input/output.         */ 
 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
 
void process_records(const char *fspec, FILE * fp); 
 
main() 
{ 
    FILE *fp; 
 
    fp = fopen("example-fixed.dat", "w", "rfm=fix", "mrs=40", "rat=none"); 
    if (fp == NULL) { 
        perror("example-fixed"); 
        exit(EXIT_FAILURE); 
    } 
    printf("Record mode\n"); 
    process_records("example-fixed.dat", fp); 
    fclose(fp); 
 
    printf("\nStream mode\n"); 
    fp = fopen("example-streamlf.dat", "w"); 
    if (fp == NULL) { 
        perror("example-streamlf"); 
        exit(EXIT_FAILURE); 
    } 
    process_records("example-streamlf.dat", fp); 
    fclose(fp); 
} 
 
void process_records(const char *fspec, FILE * fp) 
{ 
    int i, 
        sts; 
 
    char buffer[40]; 
 
    /* Write records of all 1's, all 2's and all 3's */ 
    for (i = 0; i < 3; i++) { 
        memset(buffer, '1' + i, 40); 
        sts = fwrite(buffer, 40, 1, fp); 
        if (sts != 1) { 
            perror("fwrite"); 
            exit(EXIT_FAILURE); 
        } 
    } 
 
    /* Rewind the file and write 10 characters of A's, then 10 B's, */ 
    /* then 10 C's.                                                 */ 
    /*                                                              */ 
    /* For stream mode, each fwrite call outputs 10 characters      */ 
    /* and advances the file position 10 characters                 */ 
    /* characters.                                                  */ 
    /*                                                              */ 
    /* For record mode, each fwrite merges the 10 characters  into  */ 
    /* the existing 40-character record, updates the record and     */ 
    /* advances the file position 40 characters to the next record. */ 
    rewind(fp); 
    for (i = 0; i < 3; i++) { 
        memset(buffer, 'A' + i, 10); 
        sts = fwrite(buffer, 10, 1, fp); 
        if (sts != 1) { 
            perror("fwrite2"); 
            exit(EXIT_FAILURE); 
        } 
    } 
 
    /* Now reopen the file and output the records. */ 
   
    fclose(fp); 
    fp = fopen(fspec, "r"); 
    for (i = 0; i < 3; i++) { 
        sts = fread(buffer, 40, 1, fp); 
        if (sts != 1) 
            perror("fread"); 
            printf("%.40s\n", buffer); 
    } 
 
    return; 
} 

このプログラムを実行すると,次の出力が生成されます。

Record Mode 
AAAAAAAAAA111111111111111111111111111111 
BBBBBBBBBB222222222222222222222222222222 
CCCCCCCCCC333333333333333333333333333333 
 
Stream mode 
AAAAAAAAAABBBBBBBBBBCCCCCCCCCC1111111111 
2222222222222222222222222222222222222222 
3333333333333333333333333333333333333333 



1.8 特定の移植性に関する問題

複数のシステム間でソース・プログラムを移植する予定がある場合, HP C RTL を使用するための最後の準備作業の 1 つとして, HP C RTL と,C 言語の他の実装のランタイム・ライブラリの相違点を認識することが必要です。ここでは,OpenVMS システムとの間でプログラムを移植するときに発生する可能性のある問題の一部について説明します。移植性は HP C RTL の実装に密接に関係していますが,ここでは,他の HP C for OpenVMS 構造体の移植性についても説明します。

HP C RTL では, ANSI C で定義されているライブラリ関数をはじめ,一般に使用されている多くの API や,若干の OpenVMS 拡張機能も提供されます。特定の標準のうち, HP C RTL で実装されている部分については, 第 1.4 節 を参照してください。可能な限り機能面で完全な移植性を維持するようになっています。 HP C RTL で提供される多くの標準 I/O および UNIX I/O の関数およびマクロは,他の実装の関数やマクロに機能的に対応します。

RTL 関数およびマクロの説明では,ここに示した問題の他に,ここに示していない問題についても詳しく説明しています。

次の一覧は,C プログラムを OpenVMS 環境に移植するときに考慮しなければならない問題点を示しています。

  • HP C for OpenVMS Systems はグローバル・シンボル endedataetextを実装していません。

  • OpenVMS システムと UNIX システムが仮想メモリをレイアウトする方法は異なっています。一部の UNIX システムでは,0 からブレーク・アドレスまでの間のアドレス空間はユーザ・プログラムでアクセスできます。 OpenVMS システムでは,メモリの最初のページにはアクセスできません。
    たとえば,プログラムで OpenVMS システムのロケーション 0 を参照しようとすると,ハードウェア・エラー (ACCVIO) が返され,プログラムは異常終了します。OpenVMS システムでは,ヌル・ポインタによって指されているロケーションへの参照など,不正なポインタ参照を検知するために,アドレス空間の最初のページが確保されています。この理由から,一部の UNIX システムで動作する既存のプログラムは,エラーになる可能性があり,必要に応じて変更する必要があります ( しかし,この点に関して Tru64 UNIX システムと OpenVMS システムは互換性があります )。

  • 一部の C プログラムでは, #includeファイルにすべての外部宣言が指定されることがあります。その後,初期化が必要な特定の宣言は関連モジュールで再び宣言されます。この方法でプログラミングした場合, HP C コンパイラは同じコンパイルで 2 回以上宣言された変数があることに関する警告メッセージを出力します。この警告を回避するための 1 つの方法として, #includeファイルで再宣言されるシンボルを extern変数に設定することができます。

  • OpenVMS VAX システムと OpenVMS Integrity システムで, HP C は asm呼び出しをサポートしていません。 OpenVMS Alpha システムでは,これらの呼び出しはサポートされます。組み込み関数の詳細については,『HP C User's Guide for OpenVMS Systems』を参照してください。

  • 一部の C プログラムでは,カウント付き文字列関数 strcmpnおよび strcpynが呼び出されます。これらの名前は HP C for OpenVMS Systems では使用されません。その代わり, strcmpnおよび strcpynの名前を,それに対応する ANSI 準拠の名前 strncmpおよび strncpyに拡張するマクロを定義することができます。

  • HP C for OpenVMS コンパイラでは,次の初期化形式はサポートされません。

    int  foo  123; 
    


    この初期化形式を使用するプログラムは変更する必要があります。

  • HP C for OpenVMS Systems では, __vax__alpha__ia64 __32BITS__vms
    __vaxc__VMS_VER__DECC_VER__D_FLOAT__G_FLOAT__IEEE_FLOAT
    __X_FLOATなどの複数のコンパイル時マクロをあらかじめ定義しています。これらの定義済みマクロは,他のマシンやオペレーティング・システムと互換性を維持しなければならないプログラムにとって便利です。詳細については,『HP C User's Guide for OpenVMS Systems』の定義済みマクロの章を参照してください。

  • ANSI C 言語では,宣言で変数のメモリ順序が保証されません。次の例を参照してください。

    int  a, b, c; 
    

  • 要求される外部リンクのタイプに応じて,プログラム内の extern変数は, OpenVMS システムで HP C を使用する場合, UNIX システムの場合と異なる方法で取り扱われることがあります。詳細については,『HP C User's Guide for OpenVMS Systems』を参照してください。

  • ドル記号 ($) は, HP C for OpenVMS の識別子で使用できる文字であり,1 文字目として使用できます。

  • ANSI C 言語では,関数パラメータ・リストや他の多くの式で式の評価の順序を定義していません。各 C コンパイラで式を評価する方法は,その式が副作用を持つ場合にだけ重要です。次の例について考えてみましょう。

    a[i]  =  i++; 
    

    x = func_y() + func_z(); 
    

    f(p++, p++) 
    


    HP C でも他の C コンパイラでも,このような式がすべての C コンパイラで同じ順序で評価されるという保証はありません。

  • int型の HP C 変数のサイズは, OpenVMS システムでは 32 ビットです。他のマシン用に作成され, int型の変数のサイズが異なるサイズであると仮定されているプログラムは変更する必要があります。 long型の変数は, int型の変数と同じサイズ (32 ビット) です。

  • C 言語では,コンパイラが設計されたマシンに依存する構造体アラインメントを定義しています。 OpenVMS Alpha システムでは, #pragma nomember_alignmentが指定されている場合を除き, HP C は構造体メンバを自然境界に揃えます。他の実装では,構造体メンバを異なる方法でアラインメントすることがあります。

  • HP C での構造体メンバへの参照はあいまいにすることができません。詳細については,『HP C Language Reference Manual』を参照してください。

  • レジスタは変数が使用される頻度に応じて割り当てられますが, registerキーワードは,特定の変数をレジスタに格納するかどうかに関して強力なヒントをコンパイラに与えます。可能な場合は,変数はレジスタに格納されます。ストレージ・クラスが autoまたは registerのスカラ変数は,変数のアドレスがアンパサンド演算子 (&) で参照されることがなく,構造体やユニオンのメンバでない限り,レジスタに割り当てることができます。


目次 索引

© 2012 Hewlett-Packard Development Company, L.P.