P16
解析(*(void(*)())0) ();
ステップ1:0)とandを分割、後者はアドレスの内容に対して、この式ではアドレスの内容が関数のエントリポイントであることを意味し、前者は強制的な型変換。
ステップ3:変更した変数が「戻り値がNULLの関数ポインタ」であることを解析します。2番目のステップと組み合わせると、「戻り値がNULLの関数ポインタ」ということになります。
要約すると、この文はアドレスを実行する関数を表しています。 typedefを使えば、ステートメントを簡略化できます。
typedef void(*A)();
(*(A)0) ();
P38
つの文字列sとtがありますが、それらを1つの文字列rに連結しますか?
char *r;
r = malloc(strlen(s) + strlen(t) + 1);
if (!r){
exit(1);
}
strcpy(r, s);
strcat(r, t
//メモリ空間を使い切った後);
free(r);
特筆すべきは、その手順の3つの詳細:
- malloc関数を使用してメモリを要求した後、要求が成功したかどうかをチェックする必要があります。
- 文字列は /0 で終わるので、メモリーを要求するときに余分な文字スペースを要求する必要があります。
- 要求されたメモリ領域を使用した後は、メモリリークを防ぐために解放する必要があります。
P61
つの非負整数の加算がオーバーフローするかどうかを判定します。
//エラー、オーバーフローが起こると、結果がどうなるかについてのすべての仮定はもはや有効ではない。
if(a + b < 0)
complain();
//
if((unsigned int)a + (unsigned int)b < INT_MAX)
complain();
//
if(a < INT_MAX - b)
complain();