本物のC

礼儀作法:移植性


移植性(portability)とはソースコードの「違う環境でも動かせる」度の事です。

基本的には移植性も高い方が望ましいですが、時には犠牲にすべき場合もあります。

移植性を左右する要因

CPU アーキテクチャ

代表的なものとしては 32 ビットと 64 ビットの違いがあります。これらはlongやポインタ型のサイズが異なり、無頓着にコーディングするとアーキテクチャを変えた際ほぼ確実に動かなくなります。

それを避ける為、変数や型のサイズはなるべくsizeofを使ってハードコードせず、サイズを合せる必要があるならばinttypes.hを使いましょう。

またバイトオーダーの違いも、バイナリデータを生で扱うコードでは問題になる可能性があります。

コンパイラの拡張で、特定のアーキテクチャのみで使える命令が書ける事もあります。例えば gcc の__sync_val_compare_and_swapなど。

OS

OS は一般にシステムコールへの独自の API を提供していますが、当然異なる OS では利用できません。

UNIX 系ならば POSIX 独自のライブラリ全般、Windows ならば WINAPI がそれです。

これらに関するコードは OS 毎に用意したり、プラットフォーム非依存なライブラリを利用すべきです。

コンパイラ

コンパイラは独自に C の仕様を拡張している場合があり、gcc は特に歴史が長い分それが顕著です。(Linux カーネルは元々 gcc でのコンパイルを前提にしていて、clang でもコンパイル可能にする為かなりの苦労があった様です。参考:「LLVM Clang Compiling The Linux Kernel Is A Big Topic For 2015」)

この手の拡張はなるべく避けて、標準規格の範囲でコーディングしましょう。

移植性を犠牲にする場面

移植性はそのコードを長く使っていく為に必要なものですが、そんな事よりも今一時により高いパフォーマンスを発揮してほしいという場合もあります。

パフォーマンスが移植性よりも高い価値を持つならば、上記の様な規則はどんどん破っていくべきでしょう。