• ベストアンサー

ポインタで分からないことがあります。

つい最近C言語の勉強を始め、現在ポインタの勉強をしています。 過去の質問を検索したり、サイトを見てみましたが、一人の力では解決できませんでしたので質問させていただきます。 ポインタのプログラムで、下記のプログラムについて分からないことがありました。 ――――――――――――――――――――――――――――――――― #include <stdio.h> int main (void) { char *str = "abc"; printf ("%s %d %d\n", str, &str, &(*str)); str = "日本語"; printf ("%s %d %d\n", str, &str, &(*str)); return 0; } ――――――――――――――――――――――――――――――――― このプログラムで、「char *str = "abc";」の部分でstrには abcのアドレスが入っていると思っていたのですが、 1度目の「printf ("%s %d %d\n", str, &str, &(*str));」で、 結果が「abc 1245064 4235560」となっているのを見ると 私の見解は間違っている気がします。 「char *str = "abc";」の部分では一体なにが行われているのでしょうか? また、このプログラムをコンパイルして実行した結果が、 abc 1245064 4235560 日本語 1245064 4235574 となったのですが、なぜstrのアドレスは同じなのに、 &(*str)のアドレスは異なるのでしょうか? 質問をまとめますと、以下の2つです。 1.「char *str = "abc";」の部分では一体なにが行われているのでしょうか? 2.「abc」と「日本語」のstrのアドレスは同じなのに、&(*str)のアドレスは異なるのでしょうか? 初心者ですので言葉の足らない部分があるかもしれませんが、ご教授のほどよろしくおねがいします。

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

  • ベストアンサー
  • nerosuke
  • ベストアンサー率33% (39/115)
回答No.5

どうもnerosukeです。 "日本語"は漢字で2バイトですので、解りやすい1バイトの"abc"で説明します。概念は2バイトでも同じですのであしからず。 >*str は「日本語 = アドレス」という扱いになってしまうのではないかと思うのですが 正確には "日本語"の先頭アドレスです。  "abc"で説明しますので、 char *str = "abc"; は"abc"の先頭アドレスを現します。 str == 4235560 ですよね。 で 4235560のアドレスの中身はなんでしょうか? 答えは 'a'です。 試しに出力。 printf ("%d\n", *str); //97はアスキーコードでaを表す。 printf ("%c\n", *str); //そのままaが表示 4235560 = a 4235561 = b 4235562 = c と値がメモリにあってstrには"abc"の先頭が入っているのですから、 str == 4235560 です。 *str はそのアドレスの中身の値ですから、'a'です。 &(*str)はそのアドレスの中身の値のアドレスですから、4235560です。 即ち、 str == &(*str)となるわけです。 わかりましたか? ちなみに配列はポインタそのものですので、 この辺は配列も意識しましょう。 str == str *str == str[0] &(*str) == &str[0] 配列としてこのように書いても同じ結果です。 わかりますか?

sachi-999
質問者

お礼

「char *str = "abc";」を書いた後に、「str = ○△□」を代入すると、 先に書いた「char *str = "abc";」の宣言によって、 str には ○△□ の文字ではなく ○ のアドレスが入ることになる ということですね? str に "日本語" を代入しても文字ではなくそのアドレスが入るということでようやくスッキリしました!!これで str == str *str == str[0] &(*str) == &str[0] も分かりました!! 私の何回もの質問に丁寧に答えていただき本当にありがとうございました。 良回答20点10点両方差し上げたいくらいです!! 本当にありがとうございました。またCの勉強を頑張っていきます。 機会がありましたら、また質問させていただきます。 そのときはよろしくお願いします。では。。。

その他の回答 (4)

  • nerosuke
  • ベストアンサー率33% (39/115)
回答No.4

>反対にstr のアドレスが同じなのはなぜなのでしょうか? それはchar *strはchar型のポインタ変数ですよね? &strはその変数のアドレスだからです。 "abc"も"日本語"も同じstrという変数に値を代入しています。 当然同じ変数なのでアドレスはかわりません strのアドレス == 1245064 "abc"という文字列が格納されたアドレス(先頭のアドレス) == 4235560 "日本語"という文字列が格納されたアドレス(先頭のアドレス) == 4235574 まあ 単純にこんな感じです。 変数はstrに値を入れ替えているだけなのでstrのアドレスは変わりません。 例えば str =1; str = 2; 違う値が入っても変数のアドレスは変わらないでしょ?

sachi-999
質問者

お礼

やっと理解できました!!ありがとうございます!! アドレスが「同じ」「異なる」については本当にスッキリしました!! あと、問題なのは、"日本語"の代入時です。。。 * はアドレスが指すメモリに保存されている値を表示するものですよね? str には 日本語 が代入されていてるので、 *str は「日本語 = アドレス」という扱いになってしまうのではないかと思うのですが、これでどうして &(*str) は表示できるのでしょうか? いったい * によって何を参照しているのでしょうか? 何度も質問してしまってすみません。。。

  • nerosuke
  • ベストアンサー率33% (39/115)
回答No.3

これはメモリの図を書けば一発で解るのですが、この解答欄でそれも むずかしいの「文字列 ポインタ」のキーワードで検索してみると わかりやすい図が出てくるかもしれませんね。 >1.「char *str = "abc";」の部分では一体なにが行われているのでしょうか? これはstr(charのポインタ変数)にabcの文字列が格納されたアドレスを入れています。 abc 1245064 4235560 この4235560というアドレスにabcの文字列がaから順に入っています。 なので、例えば char *abc_Adr = 4235560; //そのままアドレスの値を入れる(実際はこの値は可変) printf ("%s \n", abc_Adr); この値をそのまま入れてもabcが入った先頭が代入されいるので、 abcと出力されます。 すなわち、4235560=a,4235561=b,4235562=c とメモリ上に置かれているのです。 *str="abc" は 先頭の4235560を代入しているのです。 >2.「abc」と「日本語」のstrのアドレスは同じなのに、&(*str)のアドレスは異なるのでしょうか? 上に書いたことが理解できたら、もうお分かりかと思いますが、 "abc"同様 "日本語"というデータだメモリに置かれた先頭のアドレスを入れていますので、"abc"の先頭とはことなるのです。

sachi-999
質問者

お礼

>char *abc_Adr = 4235560; //そのままアドレスの値を入れる(実際はこの値は可変) printf ("%s \n", abc_Adr); この値をそのまま入れてもabcが入った先頭が代入されいるので、 abcと出力されます。 printf ("%s \n", abc_Adr); ならば結果は「abc」、 printf ("%d \n", abc_Adr); ならば結果は「4235560」になるということですよね? 少し理解できました!! >"abc"同様 "日本語"というデータだメモリに置かれた先頭のアドレスを入れていますので、"abc"の先頭とはことなるのです。 これは理解できました!初歩的なことを聞いて申し訳ありませんが、反対にstr のアドレスが同じなのはなぜなのでしょうか?

  • semona
  • ベストアンサー率20% (1/5)
回答No.2

>1.「char *str = "abc";」の部分では一体なにが行われているのでしょうか? strの値に"abc"のアドレスを設定しています。 ここでいうstrとはアドレスを値として保持する変数であるため "abc"のアドレス格納と言う事になります >2.「abc」と「日本語」のstrのアドレスは同じなのに、&(*str)のアドレスは異なるのでしょうか? "abc"と"日本語"というのはそれ単独で定数と言われる変数なので コンパイル時にプログラムの中の相対アドレスが設定されます。 (*str)とは変数strがさす値(ポインタですね)ですから 1回目は"abc"のアドレス、2回目は"日本語"のアドレス が格納されています。 &(*str)とはポインタが差している変数のアドレスですから "abc"と"日本語"では異なる事になります。 ちょっと回答が分かりづらいかもしれないので追加します。 |---------|--------------|----------| |変数名 |変数のアドレス| 値 | |---------|--------------|----------| |str |0x00000001 | ??? | |"abc" |0x00000002 | abc | |"日本語" |0x00000003 | 日本語 | |---------|--------------|----------| str="abc"はstrの値に「0x00000002」を設定する事です。 (*str)は「abc」ですが&(*str)は「0x00000002」ですね。 分かりましたかね? 何か説明が下手で申し訳ないです

sachi-999
質問者

お礼

char *str = "abc"; では、str はアドレスが入っていて、 str = "日本語"; では、str は"日本語"という文字が入っている という考えでイイのでしょうか? しかし、これだと、日本語を代入したあとの &(*str) は"日本語"をもとに変数を求めるて、その変数のアドレスをというというよくわからない状態になってしまうので頭がパニックになってしまいます。 どなたか、この部分を詳しく説明していただけますでしょうか? よろしくおねがいします。

回答No.1

1.「char *str = "abc";」の部分では一体なにが行われているのでしょうか? > abcのアドレスが入っていると思っていたのですが、 これで合っています。 2.「abc」と「日本語」のstrのアドレスは同じなのに、&(*str)のアドレスは異なるのでしょうか? > str = "日本語"; この部分で書き換えたからです。 printf()で表示している3種、  str  &str  &(*str) このうち str と &(*str) は同じ意味です。 *str とは簡単に言えば「strのアドレスの先頭の文字」のことであり、 それに  & が付くので「strのアドレスの先頭の文字のアドレス」となります。 ( printf ("[%s %d] [%d] [%s %d]\n", str, str, &str, &(*str), &(*str)); を表示してみてください。) &str は「str変数のアドレス」の事で、これは変動しません。 そして > str = "日本語"; この処理を行なった際に、str の中身が「"abc"の先頭アドレス」から 「"日本語"の先頭アドレス」に書き換わりました。 よって str と &(*str) が変更しました。 中身が変更されても str のアドレスは変わりませんので、 &str はそのままです。

sachi-999
質問者

お礼

回答ありがとうございます。 >> abcのアドレスが入っていると思っていたのですが、 >これで合っています。 自分が間違っていると思ったので安心しました。 >str と &(*str) は同じ意味です。 これがよく分からないのですが、 * はアドレスが指すメモリに保存されている値を表示するものではないのですか? str には 日本語 が代入されていてるので、 日本語 = アドレス?という状態になってしまうのではないかと・・・。 *によって何を参照しているのでしょうか? 物分りが悪くてすみません。。。

専門家に質問してみよう