const hoge* xとポインタを宣言した場合

前提:
typedef struct hoge {
int i;
} hoge;
hoge型を宣言しておく

①const hoge* xとポインタを宣言した場合
(xの型がconst hoge*)
xの住所はいくらでも変えられる。
(x = 1000, x = 1001, x = 1002, …という感じに)

!!*xはconst hoge
const hoge型というのは、中身を書き換えてはいけないhoge
(hogeなんだけど、中身を書き換えちゃならない)
const hogeは構造体なので…構造体の中身のメンバいずれも書き換えてはならない、ということ。!!

とある構造体の名前.メンバ名 = とある構造体を指すポインタ -> メンバ名
(*foo).bar = foo->bar。
この二つはお互いに入れ替え可能、コンパイラはこの二つを全く区別しない。
書くのが速いため(だけに)後者を使うことが多い。
実は、構造体を扱おうとするとき、構造体の名前(*foo)よりも構造体を指すポインタ(foo)を使用することが多い、ことによる。

!!つづき
(*x).i = 42; // これはできない(コンパイルエラー)
x -> iを読み出すことはできるが、
x -> i = 42などと書き込むことはできない。!!


②ポインタを宣言するということ
は、ポインタの分(=アドレスを入れる分)のメモリは確保できる。しかし、これだけではアドレスの指す先はない…つまり、家の表札だけあって家は無い(土地すら無い)状態。
だから、
ポインタの宣言→malloc or 先に別のところで変数を宣言し、モノ(家)を作って
mallocならそのallocateしたmemoryにポインタの指したい値を入れれば良いし、
後者だったら宣言した変数のアドレスを、ポインタの中に入れればok。

後者の例:
const hoge* x; // const hoge*型のポインタxを宣言
hoge y; // hoge型の変数yを宣言
y.i = 42; // hoge型変数yの中身を入れる
x = &y; // hoge型変数yぶんのメモリは確保されているので、yのアドレスをポインタxに代入

ちなみに...
y.i = 100; の変更→可能
x -> i = 100; の変更→エラー
だが...
y.i = 100; と変更すると、
x = &yのためx -> iの中身も100に変化する(!!)
const hoge型*xは、xの側からは変更ができない(定数である)のだが、
yの側からはいくらでも変えられてしまうのである...裏の手口みたいだな、なんじゃこりゃ(余り使わないほうが良いらしい)。