Estou apenas começando com ponteiros e estou um pouco confuso. Eu sei que &
significa o endereço de uma variável e que *
pode ser usado na frente de uma variável de ponteiro para obter o valor do objeto apontado pelo ponteiro. Mas as coisas funcionam de maneira diferente quando você está trabalhando com matrizes, seqüências de caracteres ou quando está chamando funções com uma cópia de ponteiro de uma variável. É difícil ver um padrão de lógica dentro de tudo isso.
Quando devo usar &
e *
?
RTFM
é inútil e, francamente, muito rude. Se você não tiver tempo para responder, seja respeitoso com quem tiver tempo para responder a essas perguntas. Eu gostaria de poder @ isso para "anon", mas obviamente ele / ela não tem tempo para contribuir de maneira significativa.Respostas:
Você tem ponteiros e valores:
Você transforma um ponteiro em um valor com
*
:Você transforma um valor em um ponteiro com
&
:Edit: No caso de matrizes, elas são tratadas como ponteiros. Se você pensar neles como ponteiros, estará usando
*
para obter os valores dentro deles, conforme explicado acima, mas também há outra maneira mais comum de usar o[]
operador:Para obter o segundo elemento:
Portanto, o
[]
operador de indexação é uma forma especial do*
operador e funciona assim:fonte
int aX[] = {3, 4}; int *bX = &aX;
int *bX = &aX;
não funciona porque oaX
já retorna o endereço deaX[0]
(ou seja&aX[0]
), então&aX
obteria o endereço de um endereço que não faz sentido. Isso está correto?int aX[] = {3,4};
,int **bX = &aX;
é um erro.&aX
é do tipo "ponteiro para matriz [2] deint
", não "ponteiro para ponteiro paraint
". Especificamente, o nome de uma matriz não é tratado como um ponteiro para seu primeiro elemento por unário&
. Você pode fazer:int (*bX)[2] = &aX;
Existe um padrão ao lidar com matrizes e funções; é um pouco difícil de ver no começo.
Ao lidar com matrizes, é útil lembrar o seguinte: quando uma expressão de matriz aparece na maioria dos contextos, o tipo da expressão é implicitamente convertido de "matriz do elemento N de T" para "ponteiro para T" e seu valor é definido para apontar para o primeiro elemento na matriz. As exceções a esta regra são quando a expressão da matriz aparece como um operando de
&
ousizeof
operadores, ou quando é uma string literal sendo usado como um inicializador em uma declaração.Portanto, quando você chama uma função com uma expressão de matriz como argumento, a função receberá um ponteiro, não uma matriz:
É por isso que você não usa o
&
operador para argumentos correspondentes a "% s" emscanf()
:Por causa da conversão implícita,
scanf()
recebe umchar *
valor que aponta para o início dastr
matriz. Isso vale para qualquer função chamada com uma expressão de matriz como argumento (praticamente qualquer uma dasstr*
funções*scanf
e*printf
funções, etc.).Na prática, você provavelmente nunca chamará uma função com uma expressão de matriz usando o
&
operador, como em:Esse código não é muito comum; você precisa conhecer o tamanho da matriz na declaração da função, e a função funciona apenas com ponteiros para matrizes de tamanhos específicos (um ponteiro para uma matriz de 10 elementos de T é um tipo diferente de um ponteiro para uma matriz de 11 elementos de T).
Quando uma expressão de matriz aparece como um operando para o
&
operador, o tipo da expressão resultante é "ponteiro para a matriz do elemento N de T" ouT (*)[N]
, que é diferente de uma matriz de ponteiros (T *[N]
) e um ponteiro para o tipo base (T *
)Ao lidar com funções e ponteiros, a regra a ser lembrada é: se você deseja alterar o valor de um argumento e refleti-lo no código de chamada, deve passar um ponteiro para o que deseja modificar. Novamente, as matrizes jogam um pouco de chave inglesa nos trabalhos, mas vamos lidar com os casos normais primeiro.
Lembre-se que C passa todos os argumentos da função por valor; o parâmetro formal recebe uma cópia do valor no parâmetro real e quaisquer alterações no parâmetro formal não são refletidas no parâmetro real. O exemplo comum é uma função de troca:
Você obterá a seguinte saída:
Os parâmetros formais
x
ey
são objetos distintos dea
eb
, portanto, muda parax
ey
não são refletidos ema
eb
. Como queremos modificar os valores dea
eb
, devemos passar ponteiros para eles para a função swap:Agora sua saída será
Observe que, na função swap, não alteramos os valores de
x
ey
, mas os valores do quex
ey
apontamos . Escrever para*x
é diferente de escrever parax
; não estamos atualizando o valor emx
si, obtemos um localx
e atualizamos o valor nesse local.Isso é igualmente verdadeiro se quisermos modificar um valor de ponteiro; se escrevermos
então estamos modificando o valor do parâmetro de entrada
stream
, não o questream
aponta para , portanto, a alteraçãostream
não afeta o valor dein
; para que isso funcione, devemos passar um ponteiro para o ponteiro:Novamente, as matrizes jogam um pouco de uma chave inglesa nos trabalhos. Quando você passa uma expressão de matriz para uma função, o que a função recebe é um ponteiro. Devido à forma como a assinatura de matriz é definida, você pode usar um operador de subscrito em um ponteiro da mesma maneira que em uma matriz:
Observe que os objetos da matriz não podem ser atribuídos; ou seja, você não pode fazer algo como
então você quer ter cuidado ao lidar com ponteiros para matrizes; algo como
não vai funcionar.
fonte
Simplificando
&
significa o endereço de , você verá que, nos espaços reservados para as funções modificarem a variável de parâmetro como em C, as variáveis de parâmetro são passadas por valor, usando os meios e comercial para passar por referência.*
significa a desreferência de uma variável de ponteiro, o que significa obter o valor dessa variável de ponteiro.O exemplo acima ilustra como chamar uma função
foo
usando passagem por referência, compare com estaAqui está uma ilustração do uso de uma desreferência
O exemplo acima ilustra como obtivemos o endereço
y
e o atribuímos à variável ponteirop
. Então, desreferenciamosp
anexando o*
à frente dele para obter o valor dep
, ie*p
.fonte
Sim, isso pode ser bastante complicado, pois
*
é usado para diversos fins em C / C ++.Se
*
aparecer na frente de uma variável / função já declarada, significa que:*
fornece acesso ao valor dessa variável (se o tipo dessa variável for do tipo ponteiro ou sobrecarregar o*
operador).*
tem o significado de operador multiplicador; nesse caso, deve haver outra variável à esquerda do*
Se
*
aparecer em uma declaração de variável ou função, significa que essa variável é um ponteiro:Se
&
aparecer em uma declaração de variável ou função, geralmente significa que essa variável é uma referência a uma variável desse tipo.Se
&
aparecer na frente de uma variável já declarada, ele retornará o endereço dessa variávelAlém disso, você deve saber que, ao passar um array para uma função, você sempre terá que passar também o tamanho do array, exceto quando o array for algo como uma cstring terminada em 0 (array de caracteres).
fonte
Ao declarar uma variável de ponteiro ou parâmetro de função, use o *:
Nota: cada variável declarada precisa de um *.
Quando você quiser usar o endereço de um valor, use &. Quando você quiser ler ou escrever o valor em um ponteiro, use *.
Matrizes geralmente são apenas tratadas como ponteiros. Quando você declara um parâmetro de matriz em uma função, pode facilmente declarar que é um ponteiro (significa a mesma coisa). Quando você passa uma matriz para uma função, na verdade você está passando um ponteiro para o primeiro elemento.
Ponteiros de função são as únicas coisas que não seguem as regras. Você pode pegar o endereço de uma função sem usar & e pode chamar um ponteiro de função sem usar *.
fonte
Eu estava olhando através de todas as explicações prolixas assim em vez virou-se para um vídeo da Universidade de Nova Gales do Sul para rescue.Here é a explicação simples: se temos uma célula que tem o endereço
x
e valor7
, a forma indireta de pedir endereço de valor7
é&7
ea forma indireta de pedir para o valor no endereçox
é*x
.Assim(cell: x , value: 7) == (cell: &7 , value: *x)
.Outra maneira de olhar para ele:John
fica na7th seat
.A*7th seat
irá apontar paraJohn
e&John
daráaddress
/ localização do7th seat
. Essa explicação simples me ajudou e espero que ajude outras pessoas também. Aqui está o link para o excelente vídeo: clique aqui.Aqui está outro exemplo:
Complemento : sempre inicialize o ponteiro antes de usá-lo. Caso contrário, o ponteiro apontará para qualquer coisa, o que pode resultar em falha do programa, porque o sistema operacional impedirá que você acesse a memória que sabe que não possui.
p = &x;
, estamos atribuindo ao ponteiro um local específico.fonte
Na verdade, você sabe disso, não há mais nada que você precise saber :-)
Gostaria apenas de adicionar os seguintes bits:
&
pega uma variável e fornece o endereço,*
pega um endereço e fornece a variável (ou conteúdo).char **p
significa quep
é um ponteiro para um ponteiro para achar
.Quanto às coisas que funcionam de maneira diferente, não realmente:
\0
caractere zero ( ).fonte
Eu acho que você está um pouco confuso. Você deve ler um bom tutorial / livro sobre ponteiros.
Este tutorial é muito bom para iniciantes (explica claramente o que é
&
e o que*
é). E sim, não esqueça de ler o livro Pointers in C, de Kenneth Reek.A diferença entre
&
e*
é muito clara.Exemplo:
fonte
Ok, parece que sua postagem foi editada ...
Veja como você pode usar o
&
para obter o endereço do início da estrutura da matriz? Os seguintesfará a mesma coisa.
fonte