- ベストアンサー
C言語の型と配列
char* str[10]={"a","b"}; char* str2="c"; としたときにstr=str2とすると 型が合わないといったエラーが出ます。 でもstrって結局はポインタの配列の先頭要素のアドレスですよね。 ポインタにポインタを入れているので通るのかなと思ったんですけど、 配列で宣言するとポインタにも型がつくのでしょうか? この例だと strは char * を10個持つ配列をさすポインタ で、 str2はchar *をさすポインタ みたいなかんじです。 質問の意味がわかりにくいですが、ご指摘をいただければ補足しますので よろしくお願いします。
- みんなの回答 (10)
- 専門家の回答
質問者が選んだベストアンサー
#8 さんへ >strは左辺値ですが、配列型ですので代入できません。 代入できないのは「左辺値ではない」からです。 宣言のときの char* str[10]={"a","b"}; str は、配列型ですが、式として参照されるとき、str はもはや配列型ではありません。 str は要素型へのポインタ、すなわち、 char のポインタへのポインタ(アドレス)です。 式として記述された str が配列型を持つのは、 ・&演算子のオペランド ・sizeof演算子のオペランド のときだけです。 int a[10];b=1; a = &b; a の型は int へのポインタ型であって配列型ではありません。代入できないのは、a が「左辺値ではない」からです。早い話、b のアドレスを格納するメモリがない(左辺値ではない)からです。 >str2=str;であれば、エラーになりません。 そうだったかもしれません。 何か、回答者の答えが、質問者をよけい混乱させているかもしれません(私も含め)。
その他の回答 (9)
- Tacosan
- ベストアンサー率23% (3656/15482)
現在の C の規格に従えば配列は左辺値です. ただし左辺値にも「変更できる左 辺値」と「変更できない左辺値」の 2種類があり, 配列は後者の「変更できない 左辺値」であるとなっています. また, 式中に表れた配列名が表すのはあくまで「配列」です. ・アドレスをとる単項演算子の & ・sizeof のオペランドになっていないときには, 自動的に「当該配列の先頭をさすポイン タ」に変換される, というだけです. 関数名も同様で, 単項 & と sizeof のオペランドになっていないときには自動 的に「当該関数の先頭アドレス」に変換されます. あくまで「現在の C の規格にてらして正しい解釈」はこうなっている, という だけですが.
- jacta
- ベストアンサー率26% (845/3158)
strの型はchar*[10]、str2の型はchar*です。 strは左辺値ですが、配列型ですので代入できません。 これは、 int a[10]; a = 123; とできないのと同じです。 str2=str;であれば、エラーになりません。 Cでは、オブジェクト型へのポインタどうしは暗黙的に型変換されます。 strは配列型ですが、代入演算子の右オペランドに指定した場合には先頭要素へのポインタ型に暗黙的に変換されます。 すなわち、strの型は、 char*[10] → char** → char* の順に暗黙的に型変換されます。 ただし、C++ではエラーになります。 この辺の区別がついていない人が多いので要注意です。
お礼
回答ありがとうございます。 確認したところ確かにC++ではエラーになり、 Cでは警告が出るだけでコンパイルできました。 Cで出来てC++で出来ないこともあるんですね。 暗黙的に変換されるというのはまったく知りませんでした・・。 というより今までちゃんと理解できてなかったみたいです。 ありがとうございました。
- komododragon
- ベストアンサー率77% (47/61)
#6 さんへ >str = "ABC"; ○ 本当?str は左辺値(l-value)ではないので代入できないと思うのだが? *str = "ABC"; ○ ならばわかります。 >str これは配列の先頭アドレスです。 実際には同じアドレスですが、意味は微妙に違います str => 配列の0番目の要素のアドレスです。 &str => 配列の先頭アドレスです。 >str=str2;とはまさに定数に変数を代入しようとする行為です。 そもそも、str には代入不可。というのが私の見解です。
- nda23
- ベストアンサー率54% (777/1415)
変数に定数は代入できます。 str = "ABC"; ○ 右辺は文字列へのアドレスで、リンク時に 確定する数値です。 定数に変数や他の定数を代入できません。 123 = str; × こんなことは理由の説明いらないですよね。 char *str[10]; これはポインタが10個あるということです。 >strは char * を10個持つ配列をさすポインタ 違います。str これは配列の先頭アドレスです。 つまり、定数です。str=str2;とはまさに定数に 変数を代入しようとする行為です。できなくて 当然ですよね。 char2がどんな型の変数であろうと定数であろうと コンパイラがどんなに進化しようと代入できません。 >str2はchar *をさすポインタ これをするなら以下のような定義です。 char **str2; または char *str2[]; そこで str2 = str; これならOKです。
お礼
とてもわかりやすく説明していただきありがとうございます。 ポインタと先頭アドレスがごっちゃになってたみたいですね・・。 すっきりしました。 本当にありがとうございました。
- morchin
- ベストアンサー率16% (212/1281)
char *str[10]は、char *型10個の配列型 char *str2は、char *型 なので、違う型同士、代入はできませんよ。 str[0] = str2; は、同じ型なので、できますが。
お礼
回答ありがとうございました。
- komododragon
- ベストアンサー率77% (47/61)
CコンパイラーがPCにインストールされていないので確かめられませんが、 str2 = str; もエラーとなるのでは? str2=(char *)str; とするとコンパイルエラーは消えそうが、意図しないことが起こりそうです。 意味のある代入としては、 str2 = str[0]; str2 = str[9]; str2 = *str; str2 = *(str+9); など。
- Tacosan
- ベストアンサー率23% (3656/15482)
あそっか, str を代入の左辺に書いたらまずいわな. str2=str; と勘違いしてた. さんきゅーです>#1. ちなみに 「この例だと strは char * を10個持つ配列をさすポインタ」 というのは間違い. str は「10個の char * からなる配列」とするのが正しい.
お礼
回答ありがとうございました。 確かに配列の言い方が正確じゃありませんでした・・。
- Tacosan
- ベストアンサー率23% (3656/15482)
C ならできていいはずだけど.... とりあえず, 使っているコンパイラと「正確な」メッセージを書いてもらえませんか? もっとも, 「大丈夫」ではあってもあまりほめられたスタイルじゃない.
補足
遅くなり申し訳ありません。 一応 コンパイラはcygwin上でgcc 3.4.4を使っています。 error: incompatible types in assignment です。
- komododragon
- ベストアンサー率77% (47/61)
str : char へのポインタのポインタ str[0] : charへのポインタ str2 : charへのポインタ str[0] = str2; ならエラーは出ない。 それに、str は、左辺値(l-value)ではないので、代入不可。 遠い記憶なので違っていたらすいません。
お礼
何度も回答していただきありがとうございます。 他の回答者のミスを指摘してもらいどっちが正しいのか考えるとより理解が深まりました。 ポインタと先頭アドレスがごっちゃになってたみたいです。 &でっていうのがとてもわかりやすかったです。 本当にありがとうございました!