Comecei a estudar C e, ao fazer um exemplo sobre a passagem de ponteiro para ponteiro como parâmetro de uma função, encontrei um problema.
Este é o meu código de exemplo:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* allocateIntArray(int* ptr, int size){
if (ptr != NULL){
for (int i = 0; i < size; i++){
ptr[i] = i;
}
}
return ptr;
}
void increasePointer(int** ptr){
if (ptr != NULL){
*ptr += 1; /* <----------------------------- This is line 16 */
}
}
int main()
{
int* p1 = (int*)malloc(sizeof(int)* 10);
allocateIntArray(p1, 10);
for (int i = 0; i < 10; i++){
printf("%d\n", p1[i]);
}
increasePointer(&p1);
printf("%d\n", *p1);
p1--;
free(p1);
fgets(string, sizeof(string), stdin);
return 0;
}
O problema ocorre na linha 16, quando modifico *ptr+=1
para *ptr++
. O resultado esperado deve ser toda a matriz e o número 1, mas quando eu uso *ptr++
o resultado é 0.
Existe alguma diferença entre +=1
e ++
? Eu pensei que os dois são iguais.
c
pointers
post-increment
huy nguyen
fonte
fonte
string
.allocateIntArray
é um nome ruim, pois parece que você émalloc
o array da função, mas não o faz. Eu sugiro emfillIntArray
vez disso. 2) Você não utiliza o valor de retorno deallocateIntArray
. Eu sugiro que você altere o tipo de retorno paravoid
. 3) Não deveif (ptr != NULL)
, em função deincreasePointer
serif (*ptr != NULL)
? 4) O elenco nãomalloc
é necessário. Veja o comentário de Sourav acima. 5) Isto:for (int i = 0; i < 10; i++){ printf("%d\n", p1[i]); }
eprintf("%d\n", *p1); p1--;
precisa ser incluídoif(p1 != NULL)
. 6)string.h
não está sendo usado.p+=1
é como++p
, não é comop++
Respostas:
A diferença é devido à precedência do operador.
O operador pós-incremento
++
tem precedência mais alta que o operador de desreferência*
. Então*ptr++
é equivalente a*(ptr++)
. Em outras palavras, o incremento de postagem modifica o ponteiro, não o que ele aponta.O operador de atribuição
+=
tem precedência mais baixa que o operador de desreferência*
, portanto*ptr+=1
é equivalente a(*ptr)+=1
. Em outras palavras, o operador de atribuição modifica o valor que o ponteiro aponta e não altera o ponteiro em si.fonte
*p++
e*++p
. A precedência do operador para este último é clara, a do primeiro.A ordem de precedência para os três operadores envolvidos na sua pergunta é a seguinte:
pós-incremento
++
> desreferência*
> atribuição+=
Você pode verificar esta página para obter mais detalhes sobre o assunto.
Para encurtar a história, para expressar essa atribuição
*ptr+=1
usando o operador pós-incremento, é necessário adicionar parênteses ao operador de desreferência para dar precedência à operação,++
como neste exemplo.(*ptr)++
fonte
Vamos aplicar parênteses para mostrar a ordem das operações
Vamos fazer de novo com
E novamente com
*ptr += 1
, incrementamos o valor da variável para a qual o ponteiro aponta .*ptr++
, incrementamos o ponteiro após a conclusão de toda a nossa declaração (linha de código) e retornamos uma referência à variável para a qual o ponteiro aponta .O último permite que você faça coisas como:
Este é um método comum usado para copiar uma
src
matriz para outradest
matriz.fonte
Muito boa pergunta.
Na K&R "linguagem de programação C" "5.1 Ponteiros e endereços", podemos obter uma resposta para isso.
"Os operadores unários * e & se ligam mais firmemente que os operadores aritméticos"
"Operadores unários como * e ++ associam da direita para a esquerda ."
// Funciona como * (ptr ++).
A maneira correta é:
fonte
* ptr + = 1: incrementa os dados para os quais ptr aponta. * ptr ++: Incrementa o ponteiro que está apontado para o próximo local da memória, em vez dos dados que o apontador aponta.
fonte