整数値からポインタ値へのキャスト (C言語)
C言語で整数型からポインタへキャストする書き方で少し詰まったため、メモします。
想定ケース
「特定のアドレスに値を直接書き込みたい」というケースを想定します。以下のようなコードを実際に見ました。
// address(0xFFFF0000)に0xFFを書き込む unsigned int address = 0xFFFF0000; *(unsigned int *) address = 0xFF
最初に整数値をunsigned int *
でポインタ型にキャストし、先頭の*
でポインタが指す場所に値を代入しています。この書き方で良いのか不明だったため、調べてみました。
適合コード
この記事によると、stdint.hで定義されるintptr_t
かuintptr_t
を使うのが良いそうです。
// address(0xFFFF0000)が指す場所に0xFFを書き込む volatile uintptr_t address = 0xFFFF0000; unsigned int *ptr = (unsigned int *)address; *ptr = 0xFF;
volatile修飾するとコンパイラはポインタへの整数代入をチェックしなくなるということです。
違反コード
期待通りにならない可能性があるコードとして、以下があります。
unsigned long *ptr = 0xFFFF0000;
どうやら処理系依存となるようです。アドレスとして与えたい整数値をポインタに変換したいときは、適合コードのような手続きを踏む必要があります。
想定ケースのコードもこれだと思いますが、処理系依存となるところでたまたまうまく動いているのでしょう。stdint.hはC99で導入されたらしく、それ以前に設計されたものはこの辺の確からしさを検証で担保していたのだと思います。
まとめ
C言語特有のポインタ操作は未だに慣れません。組み込みだとマイコン変更とかでこういう罠にハマったりしそうです。