Como incrementar o endereço de um ponteiro e o valor do ponteiro?

98

Vamos supor,

O que o código a seguir fará realmente e como?

Eu sei, isso é meio confuso em termos de codificação, mas quero saber o que realmente vai acontecer quando codificarmos assim.

Nota: Vamos supor que o endereço de a=5120300, é armazenado no ponteiro pcujo endereço é 3560200. Agora, qual será o valor de p & aapós a execução de cada instrução?

Dinesh
fonte
3
por que você simplesmente não executa no depurador?
AndersK de
24
Bem ... por que não simplesmente experimentar e ver? printfimprimirá um ponteiro com% p
Brian Roach
Se você está curioso sobre comportamento, apenas brinque com ele. Basta escrever um programa em C simples que passe por todos esses casos de uso e veja se faz sentido para você.
Cyrus de
@AndersK. Talvez o OP espere um comportamento indefinido? ...Ou talvez não.
Mateen Ulhaq

Respostas:

181

Primeiro, o operador ++ tem precedência sobre o operador * e os operadores () têm precedência sobre todo o resto.

Em segundo lugar, o operador de número ++ é o mesmo que o operador de número ++ se você não estiver atribuindo a nada. A diferença é number ++ retorna number e então incrementa number, e ++ number incrementa primeiro e então retorna.

Terceiro, ao aumentar o valor de um ponteiro, você o está incrementando pelo tamanho de seu conteúdo, ou seja, você está incrementando como se estivesse iterando em um array.

Então, para resumir tudo:

Como há muitos casos aqui, posso ter cometido algum engano, corrija-me se estiver errado.

EDITAR:

Então eu estava errado, a precedência é um pouco mais complicada do que a que escrevi, veja aqui: http://en.cppreference.com/w/cpp/language/operator_precedence

felipemaia
fonte
6
* ptr ++, o valor não é incrementado, o ponteiro sim. Esses operadores unários têm a mesma precedência, mas são avaliados da direita para a esquerda. O código significa "pegar o conteúdo de onde ptr aponta, então incrementar ptr". É um código C muito comum (e sim, bastante confuso). Corrija isso e eu removerei o downvote. O mesmo para * (ptr) ++, o parêntese não faz nada.
Lundin
Muito obrigado Lundin, perdi mais alguma coisa?
felipemaia
@Lundin Olá, a resposta acima foi corrigida agora? Obrigado.
Unheilig
4
@Unheilig A primeira frase ainda está completamente errada, postfix ++ tem precedência sobre unário * que tem a mesma precedência que prefixo ++. Tirando isso, parece ok.
Lundin,
4
@felipemaia Tem certeza de que haverá um segfault? Talvez seja apenas um comportamento indefinido?
jotik de
15

verificou o programa e os resultados são como,

Sujith R Kumar
fonte
2
@alex use significa, por exemplo, considere a instrução, 'int * a = p ++;' Aqui, o primeiro valor do ponteiro 'p' será usado para e depois disso p moverá para a próxima posição. Assim, de fato, após a execução da instrução acima, 'a' terá o endereço do local anterior apontado por 'p' e 'p' estará apontando para a próxima posição. Isso é primeiro use o valor de 'p' para a expressão de atribuição como acima e, em seguida, incremente o valor de 'p' para apontar para a próxima posição
Sujith R Kumar
Resumindo, acho que ele usa a frase "usar" para o termo mais formal "atribuir". Isso é tudo.
Apekshik Panigrahi
4

A seguir está uma instanciação das várias sugestões "basta imprimir". Eu achei instrutivo.

Retorna

Eu lancei os endereços do ponteiro para ints para que eles pudessem ser facilmente comparados.

Eu compilei com o GCC.

Rico Picone
fonte
1
Eu mudaria isso para incluir o valor de x e p após a operação.
NetJohn
3

Com relação a "Como incrementar o endereço de um ponteiro e o valor do ponteiro?" Acho que ++(*p++);está bem definido e faz o que você está pedindo, por exemplo:

Não é modificar a mesma coisa duas vezes antes de um ponto de sequência. Não acho que seja um bom estilo para a maioria dos usos - é um pouco enigmático para o meu gosto.

Flexo
fonte
Na verdade, os parênteses são desnecessários: ++*p++irá incrementar com sucesso o valor e o ponteiro (o postfix é ++mais forte do que a desreferência *, e isso acontece antes do prefixo ++devido à ordem). Os parênteses são necessários apenas quando você precisa do valor antes de incrementá-lo (*p++)++. Se você usar all-prefix, ++*++pfuncionará bem sem parênteses também (mas incrementa o valor que é apontado após o incremento do ponteiro).
cmaster - restabelecer monica
1
Abhishek DK
fonte
O que é associatividade?
71GA
1
no código você pode ver o * str ++, agora aqui * e ++ têm a mesma precedência (mesma prioridade no termo do leigo) e também * str ++ não são separados usando parênteses como * (str ++) ou (* str) ++, então torna-se necessário como deve ser avaliado. então, da direita para a esquerda significa (x = str ++) e então (y = * x)
Abhishek DK