Variáveis, ponteiros, objetos e endereços de memória: Por que recebo este resultado estranho?

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

  •  03-07-2019
  •  | 
  •  

Pergunta

Depois eu pensei que eu entendi como eles funcionam, eu tentei isso:

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

O valor de um ponteiro (como str1, str2) é um endereço de memória. Quando você vai para esse endereço, você chegar a "área" em memória onde o objeto está armazenado.

Mas: Quando eu str2 atribuir a str1, str1 deve ter como valor o endereço de memória do mesmo objeto que é referenciado por str2, certo? O estranho aqui é que o valor do ponteiro permanece a mesma (endereço de memória bfffd3cc), onde a coisa por trás dessa mudança de endereço. isso é realmente completamente unlogical para mim;) porque eu acho que o endereço de memória é o objeto (ou a casa do objeto no tijolo de memória, o que nunca). Então, eu esperava isso:

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

Caso contrário, eu ainda não chegar ao ponto. A relação entre o valor da "variável de ponteiro" e o "valor real", vamos dizer que o objeto que está sentado atrás de que o endereço de memória.

Foi útil?

Solução

Lembre-se que uma variável ponteiro é uma variável em si, por isso tem um endereço. Assim resultados &str1 no endereço da variável ponteiro, e str1 é uma expressão que resulta em qualquer que seja a variável ponteiro está segurando -. O endereço do objeto que ele está apontando para

Suponha que:

  • o objeto segurando o NSString "um" é no endereço 0x00000100
  • o objeto segurando o NSString "dois" é no endereço 0x00000200

Em seguida, seus ponteiros poderia ser algo como isto:

Na inicialização:

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

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

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

Após a atribuição str1 = str2;:

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

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

Outras dicas

estiver imprimindo a referência do ponteiro, que é o endereço do ponteiro, e não o valor do ponteiro.

&str1 leva o endereço do ponteiro.

Ok, me lembro como nós dissemos que todas as coisas "ao vivo" em algum endereço na memória? E que um ponteiro é apenas o número, um número que é o endereço?

ponteiros Bem são coisas também, e, como tal, que ter endereços.

Quando você imprimir &str1, você está imprimindo a memória ocupada pelo ponteiro. Quando você imprimir str1, você está imprimindo o valor do ponteiro, que é o endereço de memória que pontos para .

Quando você imprimir *str1 você está dereferencing o ponteiro, e imprimir que imprime o valor apontado.


Aliás, bom trabalho: Eu li suas duas últimas perguntas, e você está recebendo-o e ao seu código escrito de crédito para provar ou refutar que o seu entendimento está correto. Este é exatamente o que você deve fazer, e você está no caminho certo.

Parte do problema que você está tendo é que as cordas são coisas engraçadas, em que uma seqüência realmente um array de caracteres (const), e funções como NSLog são escritos para fazer a coisa habitual com um ponteiro para char, que é para imprimir a string. Dado um ponteiro para seqüência, é realmente looping: dereferencing o ponteiro, imprimir o caráter apontou-a, adicionando um ao ponteiro, imprimir o carácter seguinte, até que o caractere apontado é um caractere especial com o valor 0, altura em que encontrou o fim da cadeia e pára de imprimir caracteres.

Você pode encontrar tudo isso mais fácil de entender se você usar algo como ints e ponteiros para ints.

Os ponteiros são, na verdade, inteiros com uma aritmética dedicado (IIRC, é garantido que sizeof (int) == sizeof (void *))

Se você faz referência ponteiros, você poderá obter o endereço onde ele é armazenado; se a variável é automático, então você vai obter o endereço na pilha onde o ponteiro é armazenado:. é por isso que você obter esses resultados

comportam Assignment como atribuição entre números inteiros; de fato:

#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);
}

impressões:

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

str1 é um ponteiro para um valor NSString.

meios &str1: o endereço da variável str1. Este é um engano duplo.

Eu acho que você quer o endereço do valor, ou seja, str1 si só, não &str1.

Vamos supor que o valor NSString objeto contendo @"one" está localizado na 0x12345678 endereço e @"two" está em 0x1234ABC0.

Inicialmente o valor de str1 é 0x12345678 eo valor da str2 é 0x1234ABC0. Estes dois valores são armazenados na memória, respectivamente, nos endereços 0xbfffd3cc e 0xbfffd3c8. Estes são os endereços dos str1 e str2 variáveis, ou seja, valores de &str1 e &str2.

Quando você escreve str1 = str2, a atribuição altera o valor de str1 ser o mesmo que o valor de str2, ou seja, o valor de str1 é então 0x1234ABC0. Este é o endereço do objeto @"two". Mas endereço da variável str1 (0xbfffd3cc) não é alterado.

Objetos em Objective-C são trabalhadas usando ponteiros. Assim, a fim de lidar com o seu objeto NSString, você tem que tomar um ponteiro para ele. Que é o que str1 é, um ponteiro para um objeto NSString.

Se você quiser enviar uma mensagem para o NSString, você pode usar a sintaxe [str1 doSomething].

Se você deseja imprimir sua seqüência, você tem que passar o ponteiro para NSLog e dizer NSLog que o ponteiro aponta para um NSString, que é feito pela regra formatação "% @".

Agora, se você só quer imprimir o endereço apontado por str1, você ainda tem que passar o str1 ponteiro, mas você deve dizer NSLog que você está imprimindo-o como um valor hexadecimal usando a regra de formatação "% x".

Algo assim deve imprimir o que você quer:

// First print str1 as an hexadecimal value
// Then print the content of the NSString object str1 points to
NSLog(@"str1: %x, %@", str1, str1);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top