teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

アドレスを具体的に確認する方法を追加

2019/07/23 23:43

投稿

rubato6809
rubato6809

スコア1382

answer CHANGED
@@ -15,7 +15,7 @@
15
15
  - result 変数は 0x0C001248 番地にある
16
16
 
17
17
  と仮定しました。それが「"Hello" と result変数の様子」図です。
18
- 実際のアドレスどこかはともかく、何か具体的なアドレスを与えないと説明が面倒なのでテキトーにアドレスを決めました(少し工夫すれば実際のアドレスを確認できる)。
18
+ 実際のアドレスどこかはともかく、何か具体的なアドレスを与えないと説明が面倒なのでテキトーにアドレスを決めました(少し工夫すれば実際のアドレスを確認できる)。
19
19
 
20
20
  char *result; は変数宣言、或いは変数定義ですね。
21
21
  - result という名前の変数を設ける(メモリ上に割り当てる)
@@ -38,12 +38,41 @@
38
38
 
39
39
  > printf("%s", *result);とするべきのような気がする
40
40
 
41
- ここで** *result は result ポインタが指すメモリの値**で。 *result の値は 72 だということ。72 は 'H' という値なので、
41
+ ここで重要なのは** *result は result ポインタが指すメモリの値**であること。 *result の値は 72 です。72 は 'H' という値なので、
42
42
  printf("%s", 72); すなわち printf("%s", 'H'); という呼出しになります。
43
43
 
44
44
  72 という値を受け取った printf() は、運が良ければw 'H' という文字を表示できるかもしれないけれど、Hに続く0x0006A005番地の 'e' を、どうやって知るのでしょうか???
45
45
 
46
46
  こう考えれば printf("%s", *result); では期待する動作にならないことが理解できると思います。実際は "%s" を指定する限り、72 番地から始まる文字列を表示しようとして異常終了するでしょう。
47
47
 
48
- 一方、printf("%s", result); は result の値 0x0006A004 を printf() に渡します。つまり printf("%s", 0x0006A004); です。文字列の先頭アドレスを渡すので、そこから順次 H, e, l, l, o という文字を表示できる・・・これは既にご理解いただけたようですが。
48
+ 一方、printf("%s", result); は result の値 0x0006A004 を printf() に渡します。つまり printf("%s", 0x0006A004); です。文字列の先頭アドレスを渡された printf() は、そこから順次 H, e, l, l, o という文字を表示できる・・・これは既にご理解いただけたようですが。
49
- メモリの図を描くと、こういうことも実感として理解できるし、ポインタの扱いで間違いが少なくなります。
49
+ メモリの図を描くと、こういうことも実感として理解できるし、ポインタの扱いで間違いが少なくなります。
50
+
51
+ P.S.
52
+ 少し工夫すれば実際のアドレスを確認できる・・・
53
+ printf() にはポインタの値(アドレス)を表示する %p という変換指定があります。これと sizeof 演算子を使って、4行追加してみました。result の値を表示すれば "Hello" 文字列リテラルのアドレスがわかります。
54
+
55
+ ```C
56
+ #include<stdio.h>
57
+
58
+ int main(void){
59
+ char *result;
60
+ result = "Hello";
61
+ printf("%s", result);
62
+
63
+ printf("\n\n");
64
+ printf("\"Hello\" is located at %p.\n", result); // 文字列リテラルの位置
65
+ printf(" result is located at %p.\n", &result); // 変数 result の位置
66
+ printf(" size of result is %d bytes.\n", sizeof(result));
67
+ return 0;
68
+ }
69
+ ```
70
+ 私の手元では、こんな表示になりました。
71
+ ```
72
+ Hello
73
+
74
+ "Hello" is located at 0x4006f4.
75
+ result is located at 0x7ffc337f9950.
76
+ size of result is 8 bytes.
77
+ ```
78
+ result変数のサイズが8なのは64bit環境であることを示してます。もちろんデバッガでも確認できます。具体的なアドレスを知れば、より深い理解につながります。例えば、関数内のローカル変数とグローバル変数ではアドレスが大きく違うはずです。こうした情報を元にメモリの図を描きなおしてみることをお勧めします。

1

4バイトのメモリアドレス、誤りを修正

2019/07/23 23:43

投稿

rubato6809
rubato6809

スコア1382

answer CHANGED
@@ -23,7 +23,7 @@
23
23
  - そのアドレスのメモリは char 型(或いは char型配列)である
24
24
 
25
25
  という意味です。
26
- 32bitコンピュータのアドレスは 32bit ですから、result 変数には4バイトが必要です(32bit = 8bit/byte * 4byte)。この例では 0x0C001248から0x0C001247番地までの4バイトをひとまとめに使って、ひとつのアドレスを記憶します。ポインタ変数とは、そういうものです。
26
+ 32bitコンピュータのアドレスは 32bit ですから、result 変数には4バイトが必要です(32bit = 8bit/byte * 4byte)。この例では 0x0C001248から0x0C00124B番地までの4バイトをひとまとめに使って、ひとつのアドレスを記憶します。ポインタ変数とは、そういうものです。
27
27
 
28
28
  なお、メモリは1バイトだけポツンとあるわけではなく、**メモリは連続して存在するから、char一文字を指すポインタも、文字配列を指すポインタも、同じ格好**です。
29
29