私はコンピュータ工学を学ぶ、そしてここで先生は常にこのようなμCアドレスを定義するために私たちに語っていますなぜこのマクロボディに型変換がありますか?
#define FIO0DIR (* (unsigned int *) 0x2009C000) //GPIO direction register from the lpc1769
しかし、彼らは本当になぜか、何が起こっているのかを説明することはありません。
私の質問です:なぜそこにキャストはありますか?
私はコンピュータ工学を学ぶ、そしてここで先生は常にこのようなμCアドレスを定義するために私たちに語っていますなぜこのマクロボディに型変換がありますか?
#define FIO0DIR (* (unsigned int *) 0x2009C000) //GPIO direction register from the lpc1769
しかし、彼らは本当になぜか、何が起こっているのかを説明することはありません。
私の質問です:なぜそこにキャストはありますか?
どうしてですか?
0x2009C000
は整数定数です。アドレスではありません。 C型システムは、たとえターゲットアーキテクチャがアドレスでなくても、整数とアドレスを区別します。さまざまな制約のあるコンバージョンが可能ですが、ではなくの2種類があります。
整数定数を適切なポインタ型に変換するにはキャストが必要です。逆参照してそのアドレスにあるものにアクセスすることができます。
引用C11
、§6.5.3.2、アドレスと間接演算子
単項
*
演算子のオペランドはポインタ型を持たなければなりません。それ自身で
は、0x2009C000
は整数定数(§6.4.4.1章で述べたように)ではなく、ポインタ型です。
しかし、この整数定数をアドレスとして使用する予定で、値を取得するためにアドレスを尊重する必要があるため、キャストがあります。
キャストとしてunsigned int型へのポインタを整数定数値を治療するためにコンパイラに指示し、その後、間接参照演算子はそのメモリ位置に格納された値を取得するポインタに作用します。
一般的な適用としてこれを考慮しないでください。整数の定数値が(有効な)アドレス位置を表すことができるかどうかは、プラットフォームと環境に非常に依存します。
コントローラはアドレス0x2009C000にマップされていますが、それを操作するには、そのアドレスに格納または読み取るデータ型を定義する必要があります。そして、これはCのような高水準言語のためのものです:いくつかのアドレスに格納されているデータの種類、その長さ(バイト数)とその表現(2の補数の整数など)を指定します。したがって:
(unsigned int *)0x2009C000
は、符号なし整数が格納されるアドレスとしてビュー定数0x2009C000を意味します。
* ((unsigned int *)0x2009C000)
は符号なし整数を、与えられたアドレスで保存単に符号なし整数変数をに格納されたアドレスに格納された変数を意味します。
このコードは壊れています。 'volatile unsigned int *'であるか、より良いが 'volatile uint32_t *'でなければなりません。 'volatile'キーワードは、ハードウェアレジスタへのポインタを宣言するときに必須です。 – Lundin
いいえ、あなたはvolatileキーワードを持たなければなりません、あるいはコンパイラは最終的に奇妙な最適化を行うことができます。 LPCXpressoはgccを使用し、gccは非常に積極的な最適化を行います。おそらく、最適化が無効になっているために機能します。 '-O3'を試して、バグがポップアップするのを見てください。 – Lundin
あなたは正しいです、私は最適化オプションに触れたことはありません。そして、それは明らかに-O0にデフォルト設定されています。これがこれまでにすべてが機能している理由です。 – Arrrow