Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

[Dúvida] Ponteiro de ponteiro

Olá, boa noite!

Tive uma dúvida sobre ponteiro de ponteiro no seguinte código:

int numeros[5][10];

int* linha0 = numeros[0];
int* linha1 = numeros[1];
int* linha2 = numeros[2];
int* linha3 = numeros[3];
int* linha4 = numeros[4];

// os numeros serao iguais, afinal
// ambos ponteiros apontam para o mesmo 
// endereço de memória
printf("%d %d", linha0, numeros[0]);

'Veja que no código acima, declaramos int* para representar cada array que está dentro da matriz.'

Como um vetor é um meio de ordenar endereços de memória de maneira sequencial, não seria equivalente a representação através do código:

int numeros[5][10], *p;

p=numeros[numero de 0 a 5] ou até mesmo p=&numeros[0 a 5][0 a 10]? (Referenciando ao pointer unidimensional um array unidimensional (exemplo: p=numero[3] (aponta para o array presente na linha 4), e depois definindo a coluna por p[0 a 10])

Com o (* p) dando acesso ao valor interno presente na célula referenciada, o (** variavel_qualquer) poderia manipular o valor numa célula específica ao linkar com o (* p).

Ao fazer int* linha0 = numeros[0];, não seria análogo a dizer que * p[0 a 10])=numero[0][0 a 10] diretamente? Se sim, se pode linkar um endereço a uma chave de acesso a esse endereço?

3 respostas

Olá, Nickolas! Bom dia!

Vamos tentar esclarecer sua dúvida sobre ponteiros de ponteiros e como eles se relacionam com arrays e matrizes em C.

Quando você declara uma matriz como int numeros[5][10];, você está criando um array de arrays. Cada numeros[i] é, na verdade, um ponteiro para o início do array de 10 inteiros da linha i. Assim, quando você faz int* linha0 = numeros[0];, está criando um ponteiro linha0 que aponta para o primeiro elemento da primeira linha da matriz.

Agora, sobre a sua pergunta se *p[0 a 10] seria equivalente a numeros[0][0 a 10], a resposta é sim, em termos de acesso aos elementos. Quando você faz p = numeros[3];, p passa a apontar para o início da quarta linha da matriz, e você pode acessar os elementos dessa linha usando p[0], p[1], etc., que seriam equivalentes a numeros[3][0], numeros[3][1], etc.

Quanto ao ponteiro de ponteiro, int** copia = numeros; é uma forma de criar um ponteiro que aponta para o início da matriz inteira. Isso significa que copia pode ser usado para acessar qualquer elemento da matriz da mesma forma que numeros é usado, como em copia[0][0].

A ideia de "linkar um endereço a uma chave de acesso" é um pouco mais abstrata, mas em termos práticos, você está simplesmente criando referências a locais específicos na memória usando ponteiros. Isso permite manipular os dados de forma eficiente e flexível.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

/* Tome prev e def como um valores a seres definidos arbitrariamente */

p0=A[0]=&A[0][0] -> A[0]=&A[0][0] <-> (* A[0] )=A[0][0] (seguindo a ideia do array como ponteiro). * p0[def] = A[0][def] (A[0] é um ponteiro que aponta para um array e * p0[def] encontra o seu valor numérico).

Como (* A[0] ) é um ponteiro, o int* linha0 foi declarado como uma substituição nominal a esse elemento para maior facilidade no manuseio. A[0]=linha0=p0 (seguindo a lógica do parágrafo anterior, linha0 é o array e (* linha0) encontra o seu valor numérico) .

int** copia = numeros

numeros = p(def) = linha(def)

int** copia = linha(def)

(** copia) = (* linha(def)) = valor numérico

{análogo a dizer que (* copia) = (linha 0), ou seja, (* copia) = A[prev] = &A[prev][def] -> (** copia[def] )=A[prev][def]}

Caso a lógica acima esteja correta, então a variável copia está linkada com o endereço em que cada array está (endereço da linha), depois (* copia) está linkado ao array propriamente e (** copia) ao seu valor numérico? No final, como é necessário um ponteiro para linkar variáveis diferentes, então o ponteiro de ponteiro nada mais é que um meio de linkar algo a um ponteiro já existente já no estado de (* p)?

solução!

Oi, Nickolas!

Obrigado por trazer mais detalhes para sua dúvida sobre ponteiros de ponteiros e matrizes em C. Vamos resolver isso de forma prática:

Sobre sua última dúvida, sim, sua lógica está correta em grande parte. Vou esclarecer com exemplos para facilitar o entendimento:

  1. Quando você declara int numeros[5][10];, está criando uma matriz onde:

    • numeros é o endereço do primeiro elemento, ou seja, um ponteiro para numeros[0].
    • numeros[0] é o ponteiro para o primeiro elemento da primeira linha, ou seja, &numeros[0][0].
    • O int* linha0 = numeros[0]; é equivalente a dizer que linha0 é um ponteiro que aponta para o array da primeira linha.
  2. Ao usar um ponteiro de ponteiro como int** copia = (int**)numeros;, o comportamento é o seguinte:

    • copia aponta para o endereço da matriz inteira, que na prática é o mesmo que o ponteiro numeros.
    • *copia acessa a primeira linha da matriz (equivalente a numeros[0]).
    • **copia acessa o valor do primeiro elemento da matriz (equivalente a numeros[0][0]).

Veja um exemplo prático para testar o comportamento descrito:

#include &lt;stdio.h&gt;

int main() {
    int numeros[5][10];
    int* linha0 = numeros[0];
    int** copia = (int**)numeros;

    // Inicializando a matriz
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 10; j++) {
            numeros[i][j] = i * 10 + j;
        }
    }

    // Testando acessos
    printf("Valor usando linha0[2]: %d\n", linha0[2]); // Acessa numeros[0][2]
    printf("Valor usando **copia: %d\n", **copia);     // Acessa numeros[0][0]
    printf("Valor usando *(*(copia + 1) + 3): %d\n", *(*(copia + 1) + 3)); // numeros[1][3]

    return 0;
}

Explicação dos acessos no código acima:

  • linha0[2]: Acessa o elemento da posição [0][2] porque linha0 aponta para numeros[0].
  • **copia: Acessa o elemento [0][0] porque copia aponta para o início da matriz.
  • *(*(copia + 1) + 3): Acessa o elemento [1][3] ao deslocar o ponteiro para a segunda linha (copia + 1) e depois acessar a quarta coluna (+ 3).

Sobre "linkar um endereço a uma chave de acesso": Isso é essencialmente o que você está fazendo ao usar ponteiros. Um ponteiro de ponteiro permite criar uma referência adicional a esses ponteiros, funcionando como um "nível extra" de indireção.

Fico à disposição. Abraços e bons estudos!