• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語のポインタと配列)

C言語のポインタと配列についての理解まとめ

このQ&Aのポイント
  • 配列の宣言方法やメモリ上の配置についての理解が必要です。
  • 配列の要素とメモリの関係、文字列とポインタの扱い方についても理解が必要です。
  • 複雑な多次元配列やポインタの表現方法についても理解が必要です。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tasuke22
  • ベストアンサー率33% (1799/5383)
回答No.1

1.  言葉は正確に。コンピュータが行うというのは不適切。コンパイラが行います。  "があるのと無いのはコンパイラ的に意味が変わる。強調のための表現としては使えない。 > [][3]の部分の左側の数字も勝手に代入している 代入という表現はおかしい。「暗黙の宣言」が適切。 数字を指定する明示的な宣言に対して、他の部分から数字が決まってきて明示しないでも分かるものを暗黙の宣言という。 > この時なぜ3が勝手に代入されないかがわからない 要するに言語としての文法ということになる。 全てのケースにおいて矛盾のない表現が出来るのであれば暗黙の宣言が文法的に可能である。 しかしレアケースでも矛盾が生じる場合は暗黙の宣言という方法は無理となる。 配列が二次元以上は複雑な表現が多々出るので明示宣言が必要と解釈しよう。 2. > int s = {1,2,3} s[]の単純ミスですね。 > ここまで文字列以外の配列は添え字だけで管理されている。 違う。 文字列も同じ。添字で管理するという表現は不適切。管理ではない。 あくまでもデータが存在するメモリ上のアドレスが分かれば良いだけの話。 その表現方法が言語によって違うということ。管理ではなく、表現方法ということです。 領域の確保としては、配列が連続領域かどうかは言語によるとも言える。 ただ、非連続であると非常に効率が悪くなるので、すべての言語は連続領域にしている。 文字列は文字の配列です。 3. > char s[] = "abc"とするとメモリ的にはabc\0であり、[]には4が代入され、s[1]はb自身を指す。 代入ではなく、暗黙の宣言。 > char *s = "abc"をメモリで表すとabc\0であり、 メモリで表すという表現は不適切。コンパイラの約束ということ。 > \0が来るまでを文字列と認識する。 別にこの時点で認識しているわけではない。 認識するのは、各文字列を扱う関数や、自分自身のプログラムで認識する。 この時点では、あくまでも宣言ということ。領域確保と初期値の設定をしているだけ。 > sは&s[0]とも表現できるように、最初のアドレスを指し示している。 プログラムが実際に動く場合、機械語となり最終的には全てアドレスにならなければならない。 言語の中で、これほどアドレスを意識するC言語は、ある意味原始的とも言える。 > char *s[]= {"abc","def"}をメモリ的に表現するとabc\0def\0であり、 そのような約束事はない、と思う。 "abc\0"と"def\0"が離れた場所であってもおかしくない。 たまたま今回は4バイトで1ワードだから連続する可能性は高いが、64bitコンパイラだとどうか分からない。 "ab\0"、"cd\0"のように3バイトだったら、まず連続しない。 > []には2がコンピュータにより判断されて代入される。 代入ではなく暗黙の宣言。 代入という言葉にこだわるのは、別の意味が生じるから。 代入とはあくまでも変数(プログラム内のデータ領域)に値をセットする行為。 s[2]のように[]の中に2を代入したという表現は無い。2はプログラム内の話では無く、コンパイラに指示する数値である。 > \0までを文字列として表現しようとする。 全体的な約束事として文字列としているが、この時点ではただ単に値を初期設定しているだけ。 プログラムというのは、部分的には意味は無いことが多い。ただ単に値を設定するだけとか、計算をするだけとか単純なことを行う。 プログラミングによって単純なことをつなぎ合わせて意味を持たせる。 なので、本来文字列であるところを文字列で無いように扱えるということ。 コンパイラの約束事は極単純なものばかりで、プログラミングの意味合いまで関わらない。 例えで言うならワイシャツの各布を裁断する機械があったとしよう。 ポケットの布を裁断する機械が、これはポケットであると意識しているわけではない。 ただ単に決められた形に裁断している訳で、これがコンパイラに対する指示に意味合いが似ている。 そのポケットの布をポケットの位置に縫い付けて、初めてポケットになるが、ポケット以外に利用しても自由である。これがプログラミングと意味合いが似る。 ポケットの布を文字列に置き換えると少しは私が言いたい意味が分かるかも。 > s [1] は"def"の最初のアドレスを指し示すが、s[1][1]とするとe自身を指すようになる。 近いけど解釈が少し違う。 s[1]は文字列(文字の配列)でありs[1][1]は文字である。 > この時、s[1] = &s[1][0]と表現することは可能であると考えられる。 そうですね。

pipopipoid
質問者

お礼

>レアケースでも矛盾が生じる場合 この部分は考えていませんでした。矛盾が生じたらだめですよね。まだあたったことはないですが、覚えておく必要がありますね。 >s[1][1]は文字である 非常に感動しました。今までも解釈だとなぜアドレスを示したりポインタを示したのかがわからなかったのが意味を持ちました。

pipopipoid
質問者

補足

初心者の僕が言うのもあれですが >言語の中で、これほどアドレスを意識するC言語は、ある意味原始的とも言える。 は非常にその通りですが、個人的にはすごくいい部分だと思っています。cpuを意識するレベルになるのは嫌ですが。何というか、しっかりしている感じ、文字列とそのほかがつながっている部分も割と好きです。 本題からずれてしまいすみません。

その他の回答 (1)

  • jjon-com
  • ベストアンサー率61% (1599/2592)
回答No.2

> int s[] = {1,2,3}をメモリ的に表現すると、123の順に並んでいる。 はい,その通りです。 > int s[][2] = {{1,2,3},{4,5,6}}をメモリ的に表現すると123456に並んでいる。 int s[][3] であるならその通りです。 int s[][2] であるなら {1,2,3} という3番目の要素は 左辺で指定した要素数と合わず無視されますから,1245 と並んでいます。 > ここまで文字列以外の配列は添え字だけで管理されている。 いいえ,違います。 C言語は,配列を,先頭アドレスとそこからの変位で管理します。 人間にとって分かりやすくするために添字を用いますが, 添字はコンピュータ内部的には用いられず,先頭アドレスと変位に変換されます。 sが指すアドレス ↓ +―+―+―+―+―+―+ |1|2|3|4|5|6| +―+―+―+―+―+―+ 内部的には添字を用いておらず,さらにC言語は添字の範囲検査もしていませんから 次のようなコードも書けます。 #include <stdio.h> int main() { int s[][3] = {{1,2,3},{4,5,6}}; printf("%d\n", s[0][0]); printf("%d\n", s[0][1]); printf("%d\n", s[0][2]); printf("%d\n", s[0][3]); printf("%d\n", s[0][4]); printf("%d\n", s[0][5]); printf("----\n"); printf("%d\n", s[1][0]); printf("%d\n", s[1][1]); printf("%d\n", s[1][2]); printf("%d\n", s[1][3]); printf("%d\n", s[1][4]); printf("%d\n", s[1][5]); return 0; }

pipopipoid
質問者

お礼

s[1][5]とかって無茶苦茶な数字が出ますよね? なるほど、こうもかけるんだって思いました。

関連するQ&A