Next: , Up: Library Functions


5.5.1 C関数の移植性

ほとんどの通常の関数は,足りない,またはバグがある,またはアーキテクチャ によって制限があるはずです.このセクションでは,これらの移植性の問題を目 録にしようと思います.定義からすると,このリストは常に追加が必要です.で きるだけ完全なものを保つために,我々への手助けをお願いします.

exit
古いホストでは,exitintを返すものがあることを御存知です か?これは,exitのほうがvoidより時代が古く,int を 返すという伝統が長い間あったためです.
putenv
POSIXでは,putenvは与えられた文字列を直接environに書き込む ように指定していますが,システムによってはその代わりにコピーするものもあ ります(例えば,glibc 2.0やBSD).そして,コピーが作成されたとき, unsetenvはそれを解放し,メモリリークの原因になります(例えば, FreeBSD 4がそうです).

POSIXでは,putenv("FOO")は‘FOO’を環境変数から削除するように 指定していますが,システムによっては(例えばFreeBSD 4),こうならないので, 代わりにunsetenvを使用して下さい.

MINGWでは,putenv("FOO=")の呼び出しで,空の値を挿入する代わりに, ‘FOO’を環境変数から削除します.

signalハンドラ
通常,signalvoidの型を返す関数へのハンドルを受け取ります が,古いシステムには,代わりにintを要求するものもあります.実際に 返されるintの値を利用しませんが,これは関数のプロトタイプの要求が 異なるだけです.

現在知っているシステムはすべてvoidを受け取ります.おそらく, intがK&R Cでサポートされていたのですが,もちろんvoidは利用 可能ではありませんでした.AC_TYPE_SIGNAL (see Particular Types)は,すべての状況で正しい型を構築するために使用することが可能です.

snprintf
ISO C99標準では,出力配列があまり大きくなくその他のエラーが無い場合, snprintfvsnprintfは出力を切捨て,生成された出力が必要と するバイト数を返すことになっています.古いシステムでは切り捨てられた長さ を返したり(例えば,GNU Cライブラリ2.0.xやirix 6.5),負の 値を返したり(例えば,より古いバージョンのGNU Cライブラリ),切 り捨てられなかったバッファの長さを返したり(例えば32ビットのSolaris 7)し ます.また,バグの多い古いシステムにはバッファの長さとオーバーランを無視 するもの(例えば64ビットのSoraris 7)もあります.
sprintf
ISO Cの標準では,sprintfvsprintfは書き込まれたバイト数を 返すことになっていますが,古いシステム(例えばSunOS 4)ではその代わりにバッ ファへのポインタを返すものもあります.
sscanf
様々な古いシステム,例えばHP-UX 9では,sscanfは入力文字列が(たと えそれが実際には変更されなくても)書き込み可能であることを要求します.こ れは,gccは通常,固定文字列を読み込み専用のメモリに書き込むの で(see Incompatibilities of GCC),それを使用するとき問題 になるはずです.場合によっては,フォーマット文字列が明らかに読み込み専用 であっても問題になるはずです.
strnlen
AIX 4.3は,以下の結果を生成する壊れたバージョンを提供していま す.
          strnlen ("foobar", 0) = 0
          strnlen ("foobar", 1) = 3
          strnlen ("foobar", 2) = 2
          strnlen ("foobar", 3) = 1
          strnlen ("foobar", 4) = 0
          strnlen ("foobar", 5) = 6
          strnlen ("foobar", 6) = 6
          strnlen ("foobar", 7) = 6
          strnlen ("foobar", 8) = 6
          strnlen ("foobar", 9) = 6

sysconf
_SC_PAGESIZEは標準ですが,古いシステム(例えばHP-UX 9)には,代わり に_SC_PAGE_SIZEが存在します.これは#ifdefでテスト可能です.
unlink
POSIXの仕様では,unlinkは開かれているファイルへのハンド ルがなくなった後でファイルを削除するように述べられています.全てのOS が この動作をサポートしているわけではありません.そのため,システムが unlinkを提供している場合でも,開いているファイルに対して呼び出し ても大丈夫だと仮定した移植は不可能です.例えば,Windows 9xとMEでは,その ような呼び出しは失敗します.DOSは可能ですが,OSが削除した後に ファイルへの書き込みが終了するので,ファイルシステムが駄目になります.
unsetenv
MINGWでは,unsetenvが利用不可能ですが,putenvで上述したよ うに,変数‘FOO’はputenv("FOO=")の呼び出しで削除可能です.
va_copy
ISO C99標準では,va_listをコピーするためva_copyを提供して います.古い環境でも利用可能かもしれませんが,おそらくは __va_copy(例えば厳密なC89モード)でしょう.これらは#ifdef でテスト可能です.memcpy (&dst, &src, sizeof(va_list))で代替する ことで最大の移植性となるでしょう.
va_list
va_listはポインタである必要はありません.struct(例えば Alphaのgcc)にすることが可能で,それはNULLでは移植性が無 いことを意味します.配列(例えばPowerPCでコンフィグレーションされた gcc)も可能で,それは関数のパラメータとして効果的に参照呼び出し が可能であり,ライブラリルーチンで呼び出しが返す値を修正する可能性がある (例えばGNU Cライブラリ2.1のvsnprintf)ことを意味します.
符合付の>>
通常,Cの符号付きの右シフト>>はハイビットを複製し,いわゆる“算術” シフトになります.しかし,ISO Cの標準ではその動作を要求していないので, 注意すべきです.ネイティブの算術シフトが無いプロセッサ(例えばCrayベクター システム)では,符号無しのシフトと同様に,ゼロビットがシフトインされる可 能性があります.