C confusão endereço matriz
Pergunta
dizer que temos o seguinte código:
int main(){
int a[3]={1,2,3};
printf(" E: 0x%x\n", a);
printf(" &E[2]: 0x%x\n", &a[2]);
printf("&E[2]-E: 0x%x\n", &a[2] - a);
return 1;
}
Quando compilado e executar os resultados são os seguintes:
E: 0xbf8231f8
&E[2]: 0xbf823200
&E[2]-E: 0x2
Eu entendo o resultado de & E [2] que é 8 mais o endereço do array, uma vez indexados por 2 e do tipo int (4 bytes no meu sistema de 32 bits), mas eu posso' t descobrir por que a última linha é 2 em vez de 8?
Além disso, o tipo da última linha deve ser -? Um inteiro ou um ponteiro de inteiro
Gostaria de saber se é o sistema de tipo C (kinda seleção de elenco) que fazem deste capricho?
Solução
Você tem que lembrar que o a[2]
expressão realmente significa. É exatamente equivalente a *(a+2)
. Tanto assim, que é perfeitamente legal para escrever 2[a]
vez, com efeito idêntico.
Para que isso funcione e faz sentido, ponteiro aritmética leva em conta o tipo da coisa apontada. Mas isso é cuidado nos bastidores. Você começa a simplesmente usar compensações naturais em suas matrizes, e todos os detalhes apenas trabalhar.
A mesma lógica aplica-se às diferenças de ponteiro, o que explica o seu resultado de 2
.
De acordo com o capuz, no seu exemplo o índice é multiplicado por sizeof(int)
para obter um deslocamento de byte, que é adicionado para o endereço de base da matriz. Você expor esse detalhe em suas duas marcas dos endereços.
Outras dicas
Ao subtrair ponteiros do mesmo tipo, o resultado é o número de elementos e não o número de bytes. Isso ocorre por design para que você pode facilmente matrizes de index de qualquer tipo. Se você quiser número de bytes -. Expressos os endereços para char *
Quando você incrementa o ponteiro por 1 (p + 1), em seguida, ponteiro faria aponta para próxima endereço válido por adição de (p + sizeof (Type)) bytes para p. (Se Type é int então p + sizeof (int))
Lógica semelhante vale para p-1 também (de subtrair claro, neste caso).
Se você acabou de aplicar esses princípios aqui:
Em termos simples:
a[2] can be represented as (a+2)
a[2]-a ==> (a+2) - (a) ==> 2
Assim, por trás da cena,
a[2] - a[0]
==> {(a+ (2* sizeof(int)) ) - (a+0) } / sizeof(int)
==> 2 * sizeof(int) / sizeof(int) ==> 2
A linha & E [2] -2 está fazendo ponteiro subtracção, não inteiro subtração. subtração de ponteiro (quando ambos os ponteiros apontam para dados do mesmo tipo) retorna a diferença dos endereços em dividida pelo tamanho do tipo que apontam para. O valor de retorno é um int.
Para responder à sua pergunta "update", mais uma vez a aritmética de ponteiro (desta vez ponteiro disso) está sendo realizada. Ele é feito desta forma em C para torná-lo mais fácil de "index" um pedaço de dados contíguos apontado pelo ponteiro.
Você pode estar interessado em Aritmética de ponteiro Em C de perguntas e respostas.
Basicamente, + e - operadores tomem tamanho do elemento em consideração quando usado em ponteiros
.Quando somar e subtrair ponteiros em C, você usa o tamanho do tipo de dados em vez de endereços absolutos.
Se você tem um ponteiro int e adicionar o número 2 para ele, ele vai avançar 2 sizeof * (int). Da mesma forma, se você subtrair dois ponteiros int, você vai obter o resultado em unidades de sizeof (int) em vez da diferença entre os endereços absolutos.
(Ter ponteiros usando o tamanho do tipo de dados é bastante conveniente, de modo que você, por exemplo, pode simplesmente usar p++
vez de ter que especificar o tamanho do tipo de cada vez:. p+=sizeof(int)
)
Re: "Em addtion, que tipo da última linha deve ser um inteiro, ou um ponteiro inteiro ??"
um inteiro / número. da mesma forma que a: Hoje - 01 de abril = número. não a data ??p>
Se você quiser ver a diferença byte, você terá para um tipo que é 1 byte de tamanho, como este:
printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))