変数、ポインタ、オブジェクト、およびメモリアドレス:なぜこの奇妙な結果が得られるのですか?

StackOverflow https://stackoverflow.com/questions/802717

  •  03-07-2019
  •  | 
  •  

質問

それらがどのように機能するかを理解したと思った後、私はこれを試しました:

NSString *str1 = [NSString stringWithCString:"one"];
NSString *str2 = [NSString stringWithCString:"two"];
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3cc, one
NSLog(@"str2: %x, %@", &str2, str2); //bfffd3c8, two

str1 = str2;
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3cc, two

ポインタの値(str1、str2など)はメモリアドレスです。その住所に行くと、「エリア」に到達します。オブジェクトが保存されているメモリ内。

しかし、str2をstr1に割り当てるとき、str1はstr2によって参照される同じオブジェクトのメモリアドレスを値として持つ必要がありますか?ここでの奇妙なことは、ポインターの値が同じまま(bfffd3ccメモリーアドレス)であり、そのアドレスの背後にあるものが変更されることです。私にとってメモリアドレスはオブジェクト(またはメモリブリック内のオブジェクトのホームなど)であると考えているためです。だから私はこれを期待していました:

NSString *str1 = [NSString stringWithCString:"one"];
NSString *str2 = [NSString stringWithCString:"two"];
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3cc, one
NSLog(@"str2: %x, %@", &str2, str2); //bfffd3c8, two

str1 = str2;
NSLog(@"str1: %x, %@", &str1, str1); //bfffd3c8, two

それ以外の場合、私はまだポイントを得られませんでした。 「ポインタ変数」の値との関係" real value"では、そのメモリアドレスの後ろに座っているオブジェクトを言うことができます。

役に立ちましたか?

解決

ポインタ変数は変数そのものなので、アドレスを持っていることに注意してください。したがって、& str1 はポインター変数のアドレスになり、 str1 はポインター変数が保持しているもの(結果として指すオブジェクトのアドレス)になります。 。

想定:

  • NSStringを保持するオブジェクト" one"アドレス0x00000100にある
  • NSStringを保持するオブジェクト" two"アドレス0x00000200にある

その後、ポインタは次のようになります。

初期化時:

str1
0xbfffd3c8  +---------------+
            |               |
            |  0x00000100   |
            |    ("one")    |
            +---------------+

str2
0xbfffd3cc  +---------------+
            |               |
            |  0x00000200   |
            |    ("two")    |
            +---------------+

======================================

str1 = str2; の割り当て後:

str1
0xbfffd3c8  +---------------+
            |               |
            |  0x00000200   |
            |    ("two")    |
            +---------------+

str2
0xbfffd3cc  +---------------+
            |               |
            |  0x00000200   |
            |    ("two")    |
            +---------------+

他のヒント

ポインタの参照を印刷しています。これは、ポインタの値ではなく、ポインタのアドレスです。

& str1 は、ポインターのアドレスを受け取ります。

さて、すべてのことは「ライブ」だと言ったことを思い出してください。メモリ内のあるアドレスで?そして、ポインターは単なる数字であり、アドレスである数字ですか?

ウェルポインターも物事であり、そのためそれらにはアドレスがあります。

& str1 を印刷すると、ポインターが占有しているメモリが印刷されます。 str1 を印刷すると、ポインターの値が印刷されます。これは、が指すのメモリーアドレスです。

* str1 を印刷すると、ポインターの参照が解除され、それを印刷すると、ポイントされた値が印刷されます。


ちなみに、良い仕事です。最後の2つの質問を読んで、あなたはそれを手に入れています。あなたの理解が正しいことを証明または反証するために、あなたのクレジット執筆コードに。これはまさにあなたがすべきことであり、あなたは正しい軌道に乗っています。

あなたが抱えている問題の一部は、文字列が面白いものであり、文字列は実際には(定数)文字の配列であり、NSLogのような関数はcharへのポインタで通常のことを行うために書かれていることです文字列を印刷します。文字列へのポインタが与えられると、それは本当にループしています:ポインタの逆参照、ポイント先の文字の印刷、ポインタへの追加、次の文字の印刷、ポイントされた文字が値0の特殊文字になるまで文字列の終わりを見つけ、文字の出力を停止します。

intやintへのポインターなどを使用すると、これらすべてを理解しやすくなる場合があります。

ポインターは、実際には専用の算術演算を使用した整数です(IIRC、sizeof(int)== sizeof(void *))が保証されています

ポインタを参照する場合、保存されているアドレスを取得します。変数が自動の場合、ポインターが格納されているスタックのアドレスを取得します。そのため、これらの結果が取得されます。

割り当ては整数間の割り当てのように動作します。実際:

#include <stdio.h>

int main() {
        char *str1 = "Ciao";
        char *str2 = "Mondo";
        printf("%x\n", str1);
        printf("%x\n", str2);
        str1 = str2;
        printf("%x\n", str1);
}

印刷:

:~$ ./a.out
80484f8
80484fd
80484fd

str1 は、 NSString 値へのポインターです。

&amp; str1 は、 str1 変数のアドレスを意味します。これは二重間接です。

値のアドレス、つまり&amp; str1 ではなく、 str1 が必要だと思います。

@&quot; one&quot; を含む NSString オブジェクト値がアドレス 0x12345678 および @&quot; two&quotにあると仮定しましょう; 0x1234ABC0 にあります。

最初は str1 の値は 0x12345678 で、 str2 の値は 0x1234ABC0 です。 これらの2つの値は、メモリのアドレス 0xbfffd3cc および 0xbfffd3c8 にそれぞれ保存されます。これらは、 str1 および str2 変数のアドレス、つまり&amp; str1 および&amp; str2 の値です。

str1 = str2 と記述すると、割り当てにより str1 の値が str2 の値、つまり str1 0x1234ABC0 です。これは、 @&quot; two&quot; オブジェクトのアドレスです。ただし、 str1 変数( 0xbfffd3cc )のアドレスは変更されません。

Objective-Cのオブジェクトは、ポインターを使用して処理されます。したがって、NSStringオブジェクトを処理するには、そのオブジェクトへのポインタを取得する必要があります。これは、str1がNSStringオブジェクトへのポインターであるものです。

NSStringにメッセージを送信する場合は、構文[str1 doSomething]を使用できます。

文字列を印刷する場合は、NSLogにポインターを渡し、NSLogにポインターがNSStringを指していることを伝える必要があります。これは、フォーマットルール&quot;%@&quot;によって行われます。

今、str1が指すアドレスを印刷したい場合、ポインタstr1を渡す必要がありますが、フォーマットルール&quot;%x&quot;を使用して16進値として印刷することをNSLogに伝える必要があります。

そのようなものはあなたが望むものを印刷するはずです:

// First print str1 as an hexadecimal value
// Then print the content of the NSString object str1 points to
NSLog(@"str1: %x, %@", str1, str1);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top