Jump to content
Sign in to follow this  
fredericopissarra

Uma confusão recorrente: ponteiros e arrays

Recommended Posts

Artigo original: https://is.gd/55lrpk

Alguns de vocês já devem ter lido por aqui e feito experiências com relação ao “endereço” base de um array. Considere o seguinte array:

int a[] = { 1, 2, 3, 4 };

O identificador a é, de forma bastante comum, encarado como o ponteiro para o início do array. De fato, a especificação ISO 9989 nos diz que o operador [] pode ser, seguramente, interpretado como a = *(a + i). Mas, há uma distinção sutil aqui: O identificador a não é um ponteiro! Ele é interpretado como sendo um…

“Porra, tio Fred, assim você dá um nó na minha cachola!”. O problema aparece quando usamos o operador & (endereço-de):

#include <stdio.h>
 
int a[] = { 1, 2, 3 4 };
 
int main( void )
{
  printf( "a=%p, &a=%p\n", a, &a );
}

Ao compilar e executar isso você verá que os endereços impressos são os mesmos. Como pode um ponteiro apontar para uma coisa e um ponteiro para um ponteiro apontar para a mesma coisa? Não pode! O fato é que a, usando usado em expressões, é convertido em um ponteiro, mas ele não é um. O símbolo a aqui é um array “identificado” pelo nome a.

Parece que não há diferença, não é? Então, vejamos esse outro exemplo: Se a e &a forem, de fato, o mesmo ponteiro, apontar para o próximo item do array deveria fornecer o mesmo endereço, não é?

#include <stdio.h>
 
int a[] = { 1, 2, 3 4 };
 
int main( void )
{
  printf( "a=%p, &a=%p\n", a, &a );
  printf( "next(a)=%p, next(&a)=%p\n", a + 1, &a + 1 );
}

Compilando e executando você obtém algo assim:

$ cc -O2 -o test test.c
$ ./test
a=0x563c50e5a010, &a=0x563c50e5a010
next(a)=0x563c50e5a014, next(&a)=0x563c50e5a020

Ué?! Por que &a+1 resultou em um endereço diferente de a+1? Note que em nossa tentativa de obter o endereço do próximo item com o ponteiro, no primeiro caso obtemos, corretamente, o endereço 4 bytes além da base, mas no segundo (usando &a), obtemos o endereço além do final do array (16 bytes além da base)… Isso ocorre porque os tipos dos ponteiros convertidos à partir de a são diferentes… O primeiro ponteiro, a+1 é do tipo int *, o segundo, do tipo int (*)[4]. Ou seja, a e &a fornecem o mesmo endereço porque estamos obtendo o endereço do identificador a, que aponta para o início do array. No primeiro caso (a) o identificador é convertido para um ponteiro, no segundo (&a) obtemos o “endereço-do array identificado por a.

Sim, você pode assumir que o identificador de um array seja um ponteiro para sua base, se usar apenas o nome do identificador como ponteiro (não o seu endereço), mas, além do problema acima, existe outro: O identificador de um array definido carrega consigo, em tempo de compilação, o tamanho do array. Se você usar o operador sizeof com o identificador a, obterá 16 (4 vezes o tamanho de um int), no exemplo acima… Se a fosse apenas um ponteiro, obteria 4 (i386) ou 8 (x86-64) que, aliás, é o que obterá se tentar obter sizeof(&a).

Edited by fredericopissarra
  • Curtir 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...