C言語の基礎

#define GPIO_BASE 0x40020000u
volatile uint32_t *const odr =
    (volatile uint32_t *)(GPIO_BASE + 0x14);
*odr |= 1u << 5;

マイコンの出力レジスタを、上のように宣言して使っている。この宣言についての説明として、正しいものはどれか。

  1. A*odr の値は書き換えられず、odr のほうは割り込みで変わることがあるので、使うたびに読み直される
  2. Bvolatile を付けたので、*odr |= 1u << 5 の読み出し・変更・書き込みが、途中で割り込まれない一続きの操作になる
  3. Codr が指す番地は変えられず、odr を通した読み書きは省略されずに、書いた回数だけ実際に行われる
答えと解説を見る

正解:C. odr が指す番地は変えられず、odr を通した読み書きは省略されずに、書いた回数だけ実際に行われる

const が * の右にあるので、odr というポインタ自体が変えられず、常に同じレジスタの番地を指すことを表します。指す先の uint32_t には volatile が付いているので、コンパイラは *odr の読み書きを省いたりまとめたりせず、書いた回数だけ実際にアクセスします。ただし volatile は操作を不可分にはしないので、*odr |= … の読み出しと書き込みの間に割り込みが入ることはあります。割り込みハンドラと同じレジスタを操作する場合は、その間だけ割り込みを禁止するか、ビットのセット専用のレジスタを使います。

  • A. const と volatile の対象を逆に読んだ説明です。const はポインタ自体に、volatile は指す先に付いています。
  • B. volatile はアクセスを省かせないだけで、読み出しから書き込みまでを不可分にはしません。
  • C. 正しい。ポインタ自体は const、指す先のレジスタは volatile です。
この分野を解く 分野ページへ

C言語の基礎の参考書を探す PR

Amazonの検索結果へのリンクです。Amazonのアソシエイトとして、半導体教室は適格販売により収入を得ています。

C言語の基礎のほかの問題

  1. C言語の規格でいう未定義動作の説明として、正しいものはどれか。
  2. int と unsigned int は32ビットとする。次のうち、C言語の規格で未定義動作になるものはどれか。
  3. 上の関数を gcc で最適化を有効にしてコンパイルすると、if (p == NULL) の判定が削除されることがある。その理由として正しいものはどれか。
  4. C言語の規格で、int型の大きさについて定められていることとして、正しいものはどれか。
  5. 組込みのプログラムで、32ビットの周辺レジスタの値を入れる変数を、unsigned int ではなく stdint.h の uint32_t で宣言することが多い。主な理由として正しいものはどれか。