日本-日本語 |
|
|
|
OpenVMS マニュアル |
|
HP OpenVMS
|
目次 | 索引 |
レコード出力エミュレーションの最初の部分は,論理レコードの作成です。データ・バイトをレコード・ファイルに書き込む場合,エミュレータは書き込む情報からレコード境界を調べます。バイト・ストリームでの情報の処理は,次に示すように,出力先のファイルやデバイスの属性に応じて異なります。
レコード出力エミュレーションの 2 番目の部分では,最初のステップで作成した論理レコードを書き込みます。 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_items は freadの 3 番目のパラメータ), number_items x size_of_item に等しいバイト数を読み込もうとします (size_of_item は freadの 2 番目のパラメータ)。 freadから返される値は,読み込んだバイト数を size_of_item で除算した値に等しくなります。
fwrite関数は常に少なくとも number_items で指定される数のレコードを作成します。
fgets関数と gets関数は改行文字またはレコード境界まで読み込みます。
バッファに書き込まなければならないデータがある場合, fflush関数は常にレコードを生成します。 close, fclose, fseek, lseek, rewind, fsetposの場合も同様で,これらの関数はすべて,暗黙に 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 |
複数のシステム間でソース・プログラムを移植する予定がある場合, 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 環境に移植するときに考慮しなければならない問題点を示しています。
1.8 特定の移植性に関する問題
たとえば,プログラムで OpenVMS システムのロケーション 0 を参照しようとすると,ハードウェア・エラー (ACCVIO) が返され,プログラムは異常終了します。OpenVMS システムでは,ヌル・ポインタによって指されているロケーションへの参照など,不正なポインタ参照を検知するために,アドレス空間の最初のページが確保されています。この理由から,一部の UNIX システムで動作する既存のプログラムは,エラーになる可能性があり,必要に応じて変更する必要があります ( しかし,この点に関して Tru64 UNIX システムと OpenVMS システムは互換性があります )。
int foo 123;
この初期化形式を使用するプログラムは変更する必要があります。
__vaxc,
__VMS_VER,
__DECC_VER,
__D_FLOAT,
__G_FLOAT,
__IEEE_FLOAT,
__X_FLOATなどの複数のコンパイル時マクロをあらかじめ定義しています。これらの定義済みマクロは,他のマシンやオペレーティング・システムと互換性を維持しなければならないプログラムにとって便利です。詳細については,『HP C User's Guide for OpenVMS Systems』の定義済みマクロの章を参照してください。
int a, b, c;
a[i] = i++;
x = func_y() + func_z();
f(p++, p++)
HP C でも他の C コンパイラでも,このような式がすべての C コンパイラで同じ順序で評価されるという保証はありません。
目次 | 索引 |
|