愚痴だ。
こう何十年もC/C++を使っているにもかかわらず、「配列のポインタ」「ポインタの配列」が、どっちがどっちかわからなくなる。
ネットで説明が出てくるので、困ったときには調べれば良いのだが、どうも身になっていない。
ポインタの配列は使うことが多いと思う。
文字列の配列なんかは、ポインタの配列扱いしてよいだろう。
const char *STRINGS[] = {
"Hello", "my", "name", "is", "Taro", "Hara"
};
あまり意識したことがないのだが、この「*」は、const charの方にひっついているはずだ。
for (int lp = 0; lp < sizeof(STRINGS) / sizeof(STRINGS[0]); lp++) {
printf("%s\n", STRINGS[lp]);
}
これで全部の文字列が出力されたので、まあよかろう。
優先順位が心配だから括弧で強制してしまえ!、という技が、型については使えないのが残念だ。
これができれば、優先順位を覚えていなくてもよいのだが。。。コンパイルエラーだ。
(const char *)STRINGS[] = {
"Hello", "my", "name", "is", "Taro", "Hara"
};
だから、逆に考えて、括弧を付けてコンパイルエラーになる方が優先順位が高い、と覚えれば良いのか。
つまり、「ポインタの配列」の方が優先順位が高いことになる。
ポインタの配列を関数の引数にしたいことがあるけど、ダブルポインタにキャストして渡している。
他に方法が思いつかないのよねぇ。
では、括弧を付けられる方を見ていこう。
こっちが「配列のポインタ」のはずだ。
const char (*STRINGS)[];
でも、配列って、そもそもポインタと同じ扱いなんじゃないのか?
なんでわざわざ「配列のポインタ」なんてことにしないといかんのだろう。
const char a1[] = "Hello";
const char (*STRINGS)[] = &a1;
printf("%s\n", *STRINGS);
一応、これで動く。
例として意味は無いので、何か有効な使い道を思いつけば良いのだが、使い道が思いつかないから普段使わないのだ。
でも、&a1って、a1と同じ値だよね?
printf(" a1 = %p\n", a1);
printf("&a1 = %p\n", &a1);
a1 = 0x7fffe8c5b100
&a1 = 0x7fffe8c5b100
まあ、配列はアドレスに展開されるから、それに&をつけても同じアドレスになりますわな。
だからといって、代入するときに&を取り外すとコンパイルエラーになる。
数字の問題じゃなくて、文法の問題だからだ。
レジスタのアドレス値が分かっていたとしても、ポインタとしてキャストして代入しないとエラーになるのと同じだ。
これは、なんだろう?
const char (*STRINGS[]);
gccだと「invalid initializer」になるので、文法エラーじゃなくて、初期化子の書き方が間違っている、といっているような気がするのだが。。。
const char (*STRINGS[]) = {
"Hello", "my", "name", "is", "Taro", "Hara"
};
ちっ、そんだけかい。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。