forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 4
/
portability.dd
126 lines (94 loc) · 4.32 KB
/
portability.dd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
Ddoc
$(SPEC_S 移植性に関する指針,
$(P 移植の際に生じる問題を最小に押さえる、
というのはソフトウェア工学的に、良い習慣です。
移植時に問題の生じうる箇所を少なくするテクニックとしては:
)
$(UL
$(LI 整数型や浮動小数型は保証される最小範囲の型である
と考えておきます。
また、
型のサイズが増えたとしても正しく動くようにアルゴリズムを設計しておきます。)
$(LI 浮動小数演算は、変数の保持できるサイズよりも
上の精度で実行されることがあります。
浮動小数演算の関係するアルゴリズムは、
例え計算精度がいくら上がっても正しく動作するように組みます。)
$(LI コンパイラによって並び替えが行われるかもしれない部分では、
副作用の起きる順番に依存したコードを書かないようにします。例えば:
-------
a + b + c
-------
$(P は (a + b) + c, a + (b + c), (a + c) + b, (c + b) + a,
として評価される可能性があります。括弧は演算子の結合をコントロールしますが、
評価の順序はコントロールしません。
)
$(P 特に関数の引数は、
左から右に評価されたり右から左に評価されたりと、
呼び出し規約に応じて評価順序が変化します。
)
$(P 結合的な演算子 + と * のオペランドが浮動小数点数の場合は、
この並び替えは行われません。
)
)
$(LI バイトオーダー (CPUがビッグエンディアンなのかリトルエンディアンなのか)
に依存したコードは避けましょう。)
$(LI ポインタや参照のサイズが特定の整数型と等しい
と仮定したコードは避けましょう。)
$(LI もしどうしても変数サイズを決め打ちしたいならば、
$(D assert) を入れてそのことをチェックします。
-------
assert(int.sizeof == (int*).sizeof);
-------
)
)
<h2>32bit から 64bit への移植性</h2>
$(P 64bitプロセッサやOSがだんだん使われるようになってきました。
以下のことを念頭に置いておきましょう:
)
$(UL
$(LI 整数型は、
32bitでも64bit環境でも同じサイズのままです。)
$(LI ポインタやオブジェクトへの参照は、32から64bitコードに変わることで、
4byteから8byteへとサイズが増加します。)
$(LI アドレス空間を表現する符号なし整数型としては、
$(B size_t) を使います。
配列の添え字の型も $(B size_t) であるべきです。)
$(LI アドレス空間を表現する符号付き整数型としては、
$(B ptrdiff_t) を使います。
二つのポインタの間の差を表現する型は、
$(B ptrdiff_t) であるべきです。)
$(LI $(B .length), $(B .size), $(B .sizeof), $(B .offsetof),
$(B .alignof)
プロパティの型は $(B size_t) です。)
)
<h2>エンディアン</h2>
$(P エンディアンとは、複数バイトの型がどのような順番でメモリに格納されるかの順序のことです。
よくある順序は $(I ビッグエンディアン) と
$(I リトルエンディアン) の二種類です。
コンパイラは、コンパイル先システムの種類に応じて、
バージョン識別子 $(B BigEndian) か $(B LittleEndian)
をあらかじめ定義します。
x86 システムでは常にリトルエンディアンです。
)
$(P エンディアンが問題になるのは、以下のような場面です:)
$(UL
$(LI 異なるエンディアンで書かれた
外部リソース (ファイルなど)
を扱うとき。)
$(LI $(B long) や $(B double) など複数バイトの型を、
1バイトずつ読み書きするとき。)
)
<h2>OS特有のコード</h2>
$(P システム特有のコードは、
特有の部分を別のモジュールへ分離して取り扱います。
そしてコンパイル時に、システムに応じて適切なモジュールをimportします。
)
$(P 細かい違いであれば、
システム特有モジュールに定義した定数を使って、
$(I if 文) や $(I static if 文) で分けて書くこともできます。
)
)
Macros:
TITLE=移植性に関する指針
WIKI=Portability
CATEGORY_SPEC=$0