ほとんどの通常の関数は,足りない,またはバグがある,またはアーキテクチャ によって制限があるはずです.このセクションでは,これらの移植性の問題を目 録にしようと思います.定義からすると,このリストは常に追加が必要です.で きるだけ完全なものを保つために,我々への手助けをお願いします.
exitexitがintを返すものがあることを御存知です
か?これは,exitのほうがvoidより時代が古く,int を
返すという伝統が長い間あったためです.
putenvputenvは与えられた文字列を直接environに書き込む
ように指定していますが,システムによってはその代わりにコピーするものもあ
ります(例えば,glibc 2.0やBSD).そして,コピーが作成されたとき,
unsetenvはそれを解放し,メモリリークの原因になります(例えば,
FreeBSD 4がそうです).
POSIXでは,putenv("FOO")は`FOO'を環境変数から削除するように
指定していますが,システムによっては(例えばFreeBSD 4),こうならないので,
代わりにunsetenvを使用して下さい.
MINGWでは,putenv("FOO=")の呼び出しで,空の値を挿入する代わりに,
`FOO'を環境変数から削除します.
signalハンドラsignalはvoidの型を返す関数へのハンドルを受け取ります
が,古いシステムには,代わりにintを要求するものもあります.実際に
返されるintの値を利用しませんが,これは関数のプロトタイプの要求が
異なるだけです.
現在知っているシステムはすべてvoidを受け取ります.おそらく,
intがK&R Cでサポートされていたのですが,もちろんvoidは利用
可能ではありませんでした.AC_TYPE_SIGNAL (see Particular Types)は,すべての状況で正しい型を構築するために使用することが可能です.
snprintfsnprintfとvsnprintfは出力を切捨て,生成された出力が必要と
するバイト数を返すことになっています.古いシステムでは切り捨てられた長さ
を返したり(例えば,GNU Cライブラリ2.0.xやirix 6.5),負の
値を返したり(例えば,より古いバージョンのGNU Cライブラリ),切
り捨てられなかったバッファの長さを返したり(例えば32ビットのSolaris 7)し
ます.また,バグの多い古いシステムにはバッファの長さとオーバーランを無視
するもの(例えば64ビットのSoraris 7)もあります.
sprintfsprintfとvsprintfは書き込まれたバイト数を
返すことになっていますが,古いシステム(例えばSunOS 4)ではその代わりにバッ
ファへのポインタを返すものもあります.
sscanfsscanfは入力文字列が(たと
えそれが実際には変更されなくても)書き込み可能であることを要求します.こ
れは,gccは通常,固定文字列を読み込み専用のメモリに書き込むの
で(see Incompatibilities of GCC),それを使用するとき問題
になるはずです.場合によっては,フォーマット文字列が明らかに読み込み専用
であっても問題になるはずです.
strnlen 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でテスト可能です.
unlinkunlinkは開かれているファイルへのハンド
ルがなくなった後でファイルを削除するように述べられています.全てのOS が
この動作をサポートしているわけではありません.そのため,システムが
unlinkを提供している場合でも,開いているファイルに対して呼び出し
ても大丈夫だと仮定した移植は不可能です.例えば,Windows 9xとMEでは,その
ような呼び出しは失敗します.DOSは可能ですが,OSが削除した後に
ファイルへの書き込みが終了するので,ファイルシステムが駄目になります.
unsetenvunsetenvが利用不可能ですが,putenvで上述したよ
うに,変数`FOO'はputenv("FOO=")の呼び出しで削除可能です.
va_copyva_listをコピーするためva_copyを提供して
います.古い環境でも利用可能かもしれませんが,おそらくは
__va_copy(例えば厳密なC89モード)でしょう.これらは#ifdef
でテスト可能です.memcpy (&dst, &src, sizeof(va_list))で代替する
ことで最大の移植性となるでしょう.
va_listva_listはポインタである必要はありません.struct(例えば
Alphaのgcc)にすることが可能で,それはNULLでは移植性が無
いことを意味します.配列(例えばPowerPCでコンフィグレーションされた
gcc)も可能で,それは関数のパラメータとして効果的に参照呼び出し
が可能であり,ライブラリルーチンで呼び出しが返す値を修正する可能性がある
(例えばGNU Cライブラリ2.1のvsnprintf)ことを意味します.
>>>>はハイビットを複製し,いわゆる“算術”
シフトになります.しかし,ISO Cの標準ではその動作を要求していないので,
注意すべきです.ネイティブの算術シフトが無いプロセッサ(例えばCrayベクター
システム)では,符号無しのシフトと同様に,ゼロビットがシフトインされる可
能性があります.