著者の要点は、ストレージ クラスで変数を宣言すると、register
そのアドレスを取得できなくなるため、キャスト アウェイによって値が変更される可能性のある関数に渡すことができないということですconst
。
void bad_func(const int *p) {
int *q = (int *) p; // casting away const
*q = 42; // potential undefined behaviour
}
void my_func() {
int i = 4;
const int j = 5;
register const int k = 6;
bad_func(&i); // ugly but allowed
bad_func(&j); // oops - undefined behaviour invoked
bad_func(&k); // constraint violation; diagnostic required
}
潜在的な UB を制約違反に変更すると、診断が必要になり、コンパイル時にエラーが (必要に応じて) 診断されます。
c11
5.1.1.3 診断
1 - 動作が未定義または実装定義として明示的に指定されていても、前処理の翻訳単位または翻訳単位に構文規則または制約の違反が含まれている場合、準拠する実装は少なくとも 1 つの診断メッセージを生成するものとします [...]。
6.5.3.2 アドレスおよび間接演算子
制約
1 - 単項演算子のオペランドは、 [...]ストレージ クラス指定子&
で [...] が宣言されていないオブジェクトを指定する左辺値でなければなりません。register
配列オブジェクトでの配列からポインターへの減衰register
は未定義の動作であり、診断する必要がないことに注意してください (6.3.2.1:3)。
register
左辺値のアドレスを取得することは C++ で許可されていることにも注意してくださいregister
。