| 前へ | 次へ | 目次 | 索引 |
OpenVMS Alpha システムでのみ, HP C に対して追加の算術演算ルーチンがサポートされます。これらのルーチンは <math.h>に定義されており, 表 7-1 に示したルーチンの floatバリアントと long doubleバリアントです。
float バリアントは float引数を受け付け, floatの値を返します。名前の最後に接尾語として fが付加されます。次の例を参照してください。
float cosf (float x); float tandf (float x); |
long double バリアントは long double引数を受け付け, long doubleの値を返します。名前の最後に接尾語として lが付加されます。次の例を参照してください。
long double cosl (long double x); long double tandl (long double x); |
算術演算ルーチンのバリアントはすべて,本書の「リファレンス・セクション」に説明されています。
/L_DOUBLE=64 を指定せずにコンパイルしたプログラム ( つまり,デフォルトの /L_DOUBLE=128 でコンパイルしたプログラム ) の場合,これらの HP C RTL 算術演算ルーチンの
long doubleバリアントは,『HP Portable Mathematics Library (HPML)』マニュアルに説明されている X_FLOAT エントリ・ポイントにマッピングされます。
7.2 エラーの検出
実行時エラーを検出するのに役立つように, <errno.h>ヘッダ・ファイルには,多くの ( 全部ではない ) 算術関数から返される次の 2 つのシンボル値が定義されています。
算術関数を使用する場合,外部変数 errnoを調べて,これらの値のいずれか一方または両方が格納されていないかどうかを確認し,エラーが発生している場合は適切な処置を実行します。
次のプログラムの例では, errno変数の値が EDOM でないかどうかを調べます。この値は, sqrt関数に対する入力として負の数値が指定されたことを示します。
#include <errno.h>
#include <math.h>
#include <stdio.h>
main()
{
double input, square_root;
printf("Enter a number: ");
scanf("%le", &input);
errno = 0;
square_root = sqrt(input);
if (errno == EDOM)
perror("Input was negative");
else
printf("Square root of %e = %e\n",
input, square_root);
}
|
errnoでこのシンボル値を調べなかった場合,負の値が入力されると,
sqrt関数は 0 を返します。
<errno.h>ヘッダ・ファイルの詳細については, 第 4 章 を参照してください。
7.3 <fp.h> ヘッダ・ファイル
<fp.h>ヘッダ・ファイルは, ANSI X3J11 委員会の Numerical C Extensions Group が定義している一部の機能をインプリメントしています。浮動小数点関数を広範囲にわたって使用するアプリケーションの場合は,このヘッダ・ファイルが役立ちます。
この章に示した一部の倍精度関数は,結果が表現できない範囲である場合,±HUGE_VAL ( <math.h>または <fp.h>に定義) という値を返します。これらの関数の floatバージョンは,同じ条件で HUGE_VALF ( <fp.h>にのみ定義) という値を返します。 long doubleバージョンは, HUGE_VALL ( <fp.h>に定義) という値を返します。
IEEE の無限大および NaN の値を有効にしてコンパイルされたプログラムの場合,HUGE_VAL,HUGE_VALF,HUGE_VALL という値は式であり,コンパイル時定数ではありません。次のような初期化を行うと,コンパイル時エラーが発生します。
$ CREATE IEEE_INFINITY.C #include <fp.h> double my_huge_val = HUGE_VAL ^Z $ CC /FLOAT=IEEE/IEEE=DENORM IEEE_INFINITY double my_huge_val = HUGE_VAL; .....................^ %CC-E-NEEDCONSTEXPR, In the initializer for my_huge_val, "decc$gt_dbl_infinity" is not constant, but occurs in a context that requires a constant expression. at line number 3 in file WORK1$:[RTL]IEEE_INFINITY.C;1 $ |
<math.h>および
<fp.h>の両方を使用する場合,
<math.h>は関数
isnanを定義し,
<fp.h>は同じ名前のマクロを定義します。アプリケーションで最初に取り込まれたヘッダ・ファイルが
isnanに対する参照を解決します。
7.4 例
例 7-1 は, tan, sin, cos関数がどのように動作するかを示しています。
| 例 7-1 正接 (タンジェント) 値の計算と検証 |
|---|
/* CHAP_7_MATH_EXAMPLE.C */
/* This example uses two functions --- mytan and main --- */
/* to calculate the tangent value of a number, and to check */
/* the calculation using the sin and cos functions. */
#include <math.h>
#include <stdio.h>
/* This function calculates the tangent using the sin and */
/* cos functions. */
double mytan(x)
double x;
{
double y,
y1,
y2;
y1 = sin(x);
y2 = cos(x);
if (y2 == 0)
y = 0;
else
y = y1 / y2;
return y;
}
main()
{
double x;
/* Print values: compare */
for (x = 0.0; x < 1.5; x += 0.1)
printf("tan of %4.1f = %6.2f\t%6.2f\n", x, mytan(x), tan(x));
}
|
例 7-1 は次の出力を生成します。
$ RUN EXAMPLE tan of 0.0 = 0.00 0.00 tan of 0.1 = 0.10 0.10 tan of 0.2 = 0.20 0.20 tan of 0.3 = 0.31 0.31 tan of 0.4 = 0.42 0.42 tan of 0.5 = 0.55 0.55 tan of 0.6 = 0.68 0.68 tan of 0.7 = 0.84 0.84 tan of 0.8 = 1.03 1.03 tan of 0.9 = 1.26 1.26 tan of 1.0 = 1.56 1.56 tan of 1.1 = 1.96 1.96 tan of 1.2 = 2.57 2.57 tan of 1.3 = 3.60 3.60 tan of 1.4 = 5.80 5.80 $ |
表 8-1 は, HP C Run-Time Library (RTL) のすべてのメモリ割り当て関数を示しています。各関数の詳細については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』「リファレンス・セクション」を参照してください。
| 関数 | 説明 |
|---|---|
| brk, sbrk | プログラムで使用されていない最下位仮想アドレスを判断する。 |
| calloc, malloc | メモリ領域を割り当てる。 |
| cfree, free | calloc , malloc , realloc 呼び出しによって割り当てられている領域を解放して,再割り当てできるようにする。 |
| realloc | 最初の引数によって示される領域のサイズを, 2 番目の引数によって指定されるバイト数に変更する。 |
| strdup | 重複する文字列を提供し,その文字列を指し示す。 |
ヒープから追加記憶域を要求するすべての HP C RTL 関数は, HP C RTL のメモリ割り当て関数 malloc, calloc, realloc, free, cfreeを使用して,その記憶域を取得します。これらの関数によって割り当てられるメモリは,クォドワード境界に揃えられます。
ANSI C 標準には, cfreeは含まれていません。この理由から,メモリの割り当てを解除するには,同じ機能を実行する free関数を使用するようにしてください。
brk関数と sbrk関数では,メモリはアドレス空間の一番上から連続的に割り当てることができるものと仮定されています。しかし, malloc関数と RMS は,これと同じアドレス空間から領域を割り当てる可能性があります。 mallocを使用する HP C RTL ルーチンや RMS と組み合わせて, brk関数および sbrk関数を使用しないでください。
VAX C RTL に関するドキュメントの以前のバージョンには,メモリ割り当てルーチンは OpenVMS RTL の関数 LIB$GET_VM を使用して動的メモリを取得し, LIB$FREE_VM を使用して動的メモリを返すと示されていました。しかし,現在はこのようになっていません。これらのルーチンと HP C RTL メモリ割り当てルーチンの間の相互関係の問題はなくなりました ( ただし,LIB$SHOW_VM を使用して, HP C RTL の mallocおよび freeの使用状況を追跡することはできなくなりました )。
HP C RTL のメモリ割り当て関数 calloc, malloc, realloc, freeはそれぞれ,LIB$ ルーチン LIB$VM_CALLOC, LIB$VM_MALLOC,LIB$VM_REALLOC,LIB$VM_FREE をベースにしています。
ルーチン
VAXC$CALLOC_OPT,
VAXC$CFREE_OPT,
VAXC$FREE_OPT,
VAXC$MALLOC_OPT,
VAXC$REALLOC_OPTは破棄されましたので,今後の開発では使用できません。しかし,下位互換性を維持するために,標準的な C メモリ割り当てルーチンと同等として,これらのルーチンのバージョンも提供されています。
8.1 プログラムの例
例 8-1 は malloc, calloc, free関数の使用方法を示しています。
| 例 8-1 構造体に対するメモリの割り当てと割り当ての解除 |
|---|
/* CHAP_8_MEM_MANAGEMENT.C */
/* This example takes lines of input from the terminal until */
/* it encounters a Ctrl/Z, places the strings into an */
/* allocated buffer, copies the strings to memory allocated for */
/* structures, prints the lines back to the screen, and then */
/* deallocates all the memory used for the structures. */
#include <stdlib.h>
#include <stdio.h>
#define MAX_LINE_LENGTH 80
struct line_rec { /* Declare the structure. */
struct line_rec *next; /* Pointer to next line. */
char *data; /* A line from terminal. */
};
int main(void)
{
char *buffer;
/* Define pointers to */
/* structure (input lines). */
struct line_rec *first_line = NULL,
*next_line,
*last_line = NULL;
/* Buffer points to memory. */
buffer = malloc(MAX_LINE_LENGTH);
if (buffer == NULL) { /* If error ... */
perror("malloc");
exit(EXIT_FAILURE);
}
while (gets(buffer) != NULL) { /* While not Ctrl/Z ... */
/* Allocate for input line. */
next_line = calloc(1, sizeof (struct line_rec));
if (next_line == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
/* Put line in data area. */
next_line->data = buffer;
if (last_line == NULL) /* Reset pointers. */
first_line = next_line;
else
last_line->next = next_line;
last_line = next_line;
/* Allocate space for the */
/* next input line. */
buffer = malloc(MAX_LINE_LENGTH);
if (buffer == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
}
free(buffer); /* Last buffer always unused. */
next_line = first_line; /* Pointer to beginning. */
while (next_line != NULL) {
puts(next_line->data); /* Write line to screen. */
free(next_line->data); /* Deallocate a line. */
last_line = next_line;
next_line = next_line->next;
free(last_line);
}
exit(EXIT_SUCCESS);
}
|
次の例は, 例 8-1 の入力と出力を示しています。
$ RUN EXAMPLE line one line two [Ctrl/Z] EXIT line one line two $ |
オペレーティング・システムの開発には,C プログラミング言語が適しています。たとえば,UNIX オペレーティング・システムの大部分は C で書かれています。システム・プログラムを作成する場合,プログラムが動作する環境を検索または変更しなければならないことがあります。この章では,このような作業やその他のシステム・タスクを実行するための HP C Run-Time Library (RTL) 関数について説明します。
表 9-1 は, HP C RTL で提供されるすべてのシステム関数を示しています。各関数の詳細については,『HP C ランタイム・ライブラリ・リファレンス・マニュアル (下巻)』「リファレンス・セクション」を参照してください。
| 関数 | 説明 |
|---|---|
| システム関数---検索およびソート・ユーティリティ | |
| bsearch | ソートされたオブジェクトの配列でバイナリ検索を実行して,指定されたオブジェクトを検索する。 |
| qsort | クイック・ソート・アルゴリズムをインプリメントすることにより,オブジェクトの配列をソートする。 |
| システム関数---プロセス情報の検索 | |
| ctermid | SYS$COMMAND の同値文字列を与える文字列を返す。これは制御端末の名前である。 |
| cuserid | 現在のプロセスを開始したユーザの名前を格納した文字列を指すポインタを返す。 |
| getcwd | 現在のワーキング・ディレクリのファイル指定を指すポインタを返す。 |
|
getegid
,
geteuid
,
getgid , getuid |
OpenVMS の用語で,ユーザ識別コード (UIC) からグループ番号とメンバ番号を返す。 |
| getenv | 現在のプロセスの環境配列を検索し,指定された環境に関連付けられている値を返す。 |
| getlogin | 現在のセッションに関連付けられているユーザのログイン名を取得する。 |
| getpid | 現在のプロセスのプロセス ID を返す。 |
| getppid | 呼び出しプロセスの親プロセス ID を返す。 |
| getpwnam | ユーザ・データベース内のユーザ名情報にアクセスする。 |
| getpwuid | ユーザ・データベース内のユーザ ID 情報にアクセスする。 |
| システム関数---プロセス情報の変更 | |
| chdir | デフォルト・ディレクトリを変更する。 |
| chmod | ファイルのファイル保護を変更する。 |
| chown | ファイルのオーナのユーザ識別コード (UIC) を変更する。 |
| mkdir | ディレクトリを作成する。 |
| nice | 引数に指定された値だけ,プロセスの基本優先順位に対してプロセス優先順位を上げる,または下げる。 |
| putenv | 環境変数を設定する。 |
| setenv | 現在の環境リストに環境変数名を挿入する,またはリセットする。 |
| setgid, setuid | プログラムの移植性を確保するためにインプリメントされており,機能はない。 |
| sleep , usleep | 少なくとも引数に指定された秒数だけ,現在のプロセスの実行を停止する。 |
| umask | 新しいファイルが作成されるときに使用されるファイル保護マスクを作成する。古いマスクの値を返す。 |
| システム関数---日付/時刻情報の取得と変換 | |
| asctime | 年月日時分秒形式の時刻を 26 文字の文字列に変換する。 |
| clock | プログラムの実行開始以降に使用された CPU 時間をマイクロ秒単位で判断する。 |
| clock_getres | 指定されたクロックの精度を取得する。 |
| clock_gettime | 指定されたクロックの現在の時刻 (秒およびナノ秒) を返す。 |
| clock_settime | 指定されたクロックを設定する。 |
| ctime | 秒単位の時刻を asctime 関数で生成される形式の ASCII 文字列に変換する。 |
| decc$fix_time | OpenVMS のバイナリ・システム時刻を UNIX のバイナリ時刻に変換する。 |
| difftime | 引数によって指定される 2 つの時刻の差を秒単位で計算する。 |
| ftime | 1970 年 1 月 1 日 00:00:00 からの経過時間を timeb 構造体に返す。 |
| getclock | システム単位で設定されているクロックの現在の値を取得する。 |
| getdate | 書式設定された文字列を時刻/日付構造体に変換する。 |
| getitimer | 間隔タイマの値を返す。 |
| gettimeofday | 日付と時刻を取得する。 |
| gmtime | 時間単位を年月日時分秒形式の UTC 時刻に変換する。 |
| localtime | 時刻 (1970 年 1 月 1 日 00:00:00 からの経過時間を秒数で表現した時刻) を時,分,秒などに変換する。 |
| mktime | ローカル時刻構造体を Epoch (1970 年 1 月 1 日 00:00:00) からの経過時間に変換する。 |
| nanosleep | 高精度の sleep (リアルタイム)。指定された時間,プロセスの実行を一時停止する。 |
| setitimer | 間隔タイマの値を設定する。 |
| strftime, wcsftime | 指定された書式文字列による制御のもとで,配列に文字を格納する。 |
| strptime | 文字列を日付と時刻の値に変換する。 |
| time | 1970 年 1 月 1 日 00:00:00 からの経過時間を秒単位で返す。 |
| times | 現在のプロセスと終了した子プロセスの累積時間を返す。 |
| tzset | タイム・ゾーン変換を設定する,またはタイム・ゾーン変換にアクセスする。 |
| ualarm | 間隔タイマの時間切れを設定または変更する。 |
| wcsftime | tm 構造体に格納されている日付と時刻の情報を使用して,ワイド文字の出力文字列を作成する。 |
| システム関数---その他 | |
| VAXC$CRTL_INIT | 実行時環境を初期化し,終了および条件ハンドラを設定する。この結果, HP C RTL 関数を他の言語から呼び出すことができるようになる。 |
例 9-1 は, cuserid関数の使用方法を示しています。
| 例 9-1 ユーザ名へのアクセス |
|---|
/* CHAP_9_GET_USER.C */
/* Using cuserid, this program returns the user name. */
#include <stdio.h>
main()
{
static char string[L_cuserid];
cuserid(string);
printf("Initiating user: %s\n", string);
}
|
| 前へ | 次へ | 目次 | 索引 |