厳格なルールを破っているキャスト
-
04-10-2019 - |
質問
署名されていない長い*を取る関数があり、署名されていないint*を取る外部ライブラリに渡す必要があります。
void UpdateVar(unsigned long* var) {
// this function will change the value at the address of var
ExternalLibAtomicUpdateVar((unsigned int*)var); // lib atomically updates variable
}
これにより、厳格な規則を破るという警告が生成されます。回避策はありますか?
ありがとうございました
編集:明確でないことをお詫びします。コードはアトミックアップデートであるため、ライブラリを囲んで保存することはオプションではありません。アセンブリにドロップダウンすることもできますが、これをC ++でやりたいと思います。
解決
void UpdateVar(unsigned long* var) {
unsigned int x = static_cast<unsigned int>(*var);
ExternalLibUpdateVar(&x);
*var = static_cast<unsigned long>(x);
}
他のヒント
これは機能するはずです:
void UpdateVar(unsigned long* var) {
// this function will change the value at the address of var
ExternalLibUpdateVar(reinterpret_cast<unsigned int*>(var));
}
C標準には何も義務付けられていません int
と long
同じサイズが必要です。さらに、たとえ同じサイズを持っていても、標準的な任務には同じ表現があるという義務はありません(とりわけ、パディングビットとトラップ表現の互換性のない組み合わせがある可能性があります。有用な目的)。
標準の著者は、間でエイリアシングするプラットフォームをターゲットとする実装者を強制したくありませんでした int
と long
そのようなエイリアシングを認識する目的は役に立たないでしょう。彼らはまた、一部のプラットフォーム(エイリアシングが目的に役立つもの)に適用できるルールを書きたくありませんでしたが、他のプラットフォーム(それがそうしない場合)はありませんでした。代わりに、彼らは、質の高いコンパイラを書く人々が、それが有用である場合にエイリアシングを認識しようとすると考えました。
ポインターを1つの32ビットタイプに使用して、同じ表現を持つ別の32ビットタイプの値を読み書きできることが明らかに役立ちます。プラットフォームで一般的なAPIが使用される場合 int*
32ビット値およびその他の使用の場合 long*
, 、a 品質 そのプラットフォームの汎用実装では、他のポインターを使用して、いずれかのタイプのデータにアクセスできるようにする必要があります。
しかし、残念ながら、一部のコンパイラの著者は、プログラムのより大きなサブセットを有用に処理するよりも、プログラムの特定のサブセットを迅速に処理することに関心があり、使用するAPI間でデータを交換する必要がある場合は有用なコードを生成するために依存することはできません。同じデータ表現ですが、エイリアシング分析を完全に無効にしない限り、異なる名前のタイプ。もちろん、マイクロコントローラーでの汎用使用に適したCの方言をターゲットにしている場合、そのような問題は重要ではありません。