Em C, qual é a diferença entre using ++i
e i++
, e qual deve ser usada no bloco de incremento de um for
loop?
c
for-loop
post-increment
pre-increment
The.Anti.9
fonte
fonte
Respostas:
++i
aumentará o valor dei
e retornará o valor incrementado.i++
aumentará o valor dei
, mas retornará o valor original que erai
mantido antes de ser incrementado.Para um
for
loop, qualquer um funciona.++i
parece mais comum, talvez porque é isso que é usado em K&R .De qualquer forma, siga a diretriz "prefira
++i
sobrei++
" e você não errará.Há alguns comentários sobre a eficiência de
++i
ei++
. Em qualquer compilador de projeto que não seja aluno, não haverá diferença de desempenho. Você pode verificar isso observando o código gerado, que será idêntico.A questão da eficiência é interessante ... aqui está minha tentativa de resposta: Existe uma diferença de desempenho entre i ++ e ++ i em C?
Como o @OnFreund observa, é diferente para um objeto C ++, pois
operator++()
é uma função e o compilador não pode saber como otimizar a criação de um objeto temporário para armazenar o valor intermediário.fonte
for(int i=0; i<10; i++){ print i; }
isso não será diferente do quefor(int i=0; i<10; ++i){ print i; }
Meu entendimento é que alguns idiomas fornecerão resultados diferentes dependendo de qual você usar.i++
porque é da forma "operando-operador", como uma atribuição "operando-operador-valor". Em outras palavras, o operando de destino está no lado esquerdo da expressão, assim como em uma declaração de atribuição.i++
eprint i
esteja em declarações diferentes, mas porquei++;
ei<10
está. A observação de @ jonnyflash não é tão estranha assim. Suponha que você tenhafor(int i=0; i++<10){ print i; }
efor(int i=0; ++i<10){ print i; }
. Eles funcionarão de maneira diferente da maneira que @johnnyflash descreveu no primeiro comentário.O i ++ é conhecido como pós-incremento, enquanto o ++ i é chamado de pré-incremento.
i++
i++
é pós-incremento porque incrementai
o valor de 1 após o término da operação.Vamos ver o seguinte exemplo:
Aqui valor de
j = 1
masi = 2
. Aqui o valor dei
será atribuídoj
primeiro e depoisi
será incrementado.++i
++i
é pré-incremento porque incrementai
o valor de 1 antes da operação. Isso significa quej = i;
será executado depoisi++
.Vamos ver o seguinte exemplo:
Aqui valor de
j = 2
masi = 2
. Aqui o valor dei
será atribuídoj
após oi
incremento dei
. Da mesma forma++i
será executado antesj=i;
.Para sua pergunta, o que deve ser usado no bloco de incremento de um loop for? a resposta é, você pode usar qualquer um .. não importa. Ele executará seu loop for mesmo não. vezes
E
Ambos os loops produzirão a mesma saída. ie
0 1 2 3 4
.Só importa onde você está usando.
Nesse caso, a saída será
1 2 3 4 5
.fonte
Por favor, não se preocupe com a "eficiência" (velocidade, na verdade) da qual é mais rápida. Atualmente, temos compiladores que cuidam dessas coisas. Use o que fizer sentido, com base no que mostra mais claramente sua intenção.
fonte
operator++(int)
(a versão do postfix), o código praticamente precisa criar um temporário que será retornado. Você tem certeza de que os compiladores sempre podem otimizar isso?++i
incrementa o valor e o retorna.i++
retorna o valor e o incrementa.É uma diferença sutil.
Para um loop for, use
++i
, pois é um pouco mais rápido.i++
criará uma cópia extra que será jogada fora.fonte
i++
: Neste cenário, primeiro o valor é atribuído e, em seguida, o incremento acontece.++i
: Neste cenário, primeiro o incremento é feito e, em seguida, o valor é atribuídoAbaixo está a visualização da imagem e também aqui está um bom vídeo prático que demonstra o mesmo.
fonte
O motivo
++i
pode ser um pouco mais rápido doi++
que oi++
necessário, pois pode exigir uma cópia local do valor de i antes que ele seja incrementado, embora++i
nunca seja necessário. Em alguns casos, alguns compiladores o otimizarão se possível ... mas nem sempre é possível, e nem todos os compiladores fazem isso.Tento não confiar muito nas otimizações dos compiladores, por isso segui o conselho de Ryan Fox: quando posso usar os dois, uso
++i
.fonte
i
que o valor 1 quando você escreve uma instrução1;
.O resultado efetivo do uso de um loop é idêntico. Em outras palavras, o loop fará a mesma coisa exata nos dois casos.
Em termos de eficiência, pode haver uma penalidade na escolha do i ++ sobre o ++ i. Em termos de especificação de idioma, o uso do operador pós-incremento deve criar uma cópia extra do valor em que o operador está agindo. Isso pode ser uma fonte de operações extras.
No entanto, você deve considerar dois problemas principais com a lógica anterior.
Compiladores modernos são ótimos. Todos os bons compiladores são inteligentes o suficiente para perceber que estão vendo um incremento inteiro em um loop for e otimizarão os dois métodos para o mesmo código eficiente. Se o uso de pós-incremento sobre pré-incremento realmente faz com que seu programa tenha um tempo de execução mais lento, você está usando um compilador terrível .
Em termos de complexidade operacional do tempo, os dois métodos (mesmo que uma cópia esteja realmente sendo executada) são equivalentes. O número de instruções executadas dentro do loop deve dominar significativamente o número de operações na operação de incremento. Portanto, em qualquer loop de tamanho significativo, a penalidade do método de incremento será massivamente ofuscada pela execução do corpo do loop. Em outras palavras, é muito melhor se preocupar em otimizar o código no loop, em vez do incremento.
Na minha opinião, toda a questão simplesmente se resume a uma preferência de estilo. Se você acha que o pré-incremento é mais legível, use-o. Pessoalmente, prefiro o pós-incremento, mas é provavelmente porque foi o que me ensinaram antes de saber algo sobre otimização.
Este é um exemplo por excelência de otimização prematura, e problemas como esse têm o potencial de nos distrair de problemas sérios no design. Ainda é uma boa pergunta, no entanto, porque não há uniformidade no uso ou consenso nas "melhores práticas".
fonte
Ambos incrementam o número.
++i
é equivalente ai = i + 1
.i++
e++i
são muito parecidos, mas não exatamente iguais. Ambos incrementam o número, mas++i
incrementam o número antes que a expressão atual seja avaliada, enquantoi++
incrementam o número após a expressão ser avaliada.Exemplo:
fonte
++i
(Operação Prefixo): Incrementos e, em seguida, atribui o valor(por exemplo,):
int i = 5
,int b = ++i
Neste caso, 6 é atribuído a B em primeiro lugar e, em seguida, a incrementos de 7 e assim por diante.i++
(Operação sufixo): Atribui e, em seguida, incrementa o valor(por exemplo,):
int i = 5
,int b = i++
Neste caso, é atribuído a 5 B em primeiro lugar e, em seguida, a incrementos de 6 e assim por diante.Caso do loop
i++
for : é usado principalmente porque, normalmente, usamos o valor inicial dei
antes de incrementar o loop for. Mas, dependendo da lógica do seu programa, isso pode variar.fonte
++i
: é pré-incremento, o outro é pós-incremento.i++
: obtém o elemento e depois o incrementa.++i
: incrementa ie retorna o elemento.Exemplo:
Resultado:
fonte
Suponho que você entenda a diferença na semântica agora (embora, honestamente, eu me pergunte por que as pessoas perguntam 'o que o operador X significa' perguntas sobre o estouro de pilha, em vez de ler, você sabe, um livro ou tutorial da Web ou algo assim.
De qualquer maneira, quanto a qual usar, ignore as questões de desempenho, que são improváveis importantes mesmo em C ++. Este é o princípio que você deve usar ao decidir qual usar:
Diga o que você quer dizer com código.
Se você não precisar do valor antes do incremento em sua declaração, não use esse formato do operador. É um problema menor, mas, a menos que você esteja trabalhando com um guia de estilo que proíbe uma versão totalmente a favor da outra (também conhecido como guia de estilo com cabeça de osso), use o formulário que expressa exatamente o que você está tentando fazer.
QED, use a versão pré-incremento:
fonte
A diferença pode ser entendida por este código C ++ simples abaixo:
fonte
fonte
i ++ e ++ i
Este pequeno código pode ajudar a visualizar a diferença de um ângulo diferente das respostas já postadas:
O resultado é:
Preste atenção às situações antes e depois.
para laço
Quanto a qual deles deve ser usado em um bloco de incremento de um loop for, acho que o melhor que podemos fazer para tomar uma decisão é usar um bom exemplo:
O resultado é:
Não sei você, mas não vejo diferença em seu uso, pelo menos em um loop for.
fonte
O seguinte fragmento de código C ilustra a diferença entre os operadores de pré e pós incremento e decremento:
Operadores de incremento:
fonte
Pré-incremento significa incremento na mesma linha. Pós-incremento significa incremento após a execução da linha.
Quando se trata de operadores OR, AND, torna-se mais interessante.
Na matriz
Em C ++ pós / pré-incremento da variável ponteiro
fonte
Em breve:
++i
ei++
funciona da mesma maneira se você não estiver gravando em uma função. Se você usar algo comofunction(i++)
oufunction(++i)
pode ver a diferença.function(++i)
diz o primeiro incremento i em 1, depois disso, coloque issoi
na função com novo valor.function(i++)
diz colocar primeiroi
na função após esse incrementoi
em 1.fonte
int j = ++i;
eint k = i++;
mesmo quando não há chamada de função envolvida.A única diferença é a ordem das operações entre o incremento da variável e o valor que o operador retorna.
Este código e sua saída explicam a diferença:
A saída é:
Então, basicamente,
++i
retorna o valor após ser incrementado, enquanto++i
retorna o valor antes de ser incrementado. No final, em ambos os casos, oi
valor será incrementado.Outro exemplo:
Resultado:
Muitas vezes não há diferença
As diferenças são claras quando o valor devolvido é atribuído a uma outra variável ou quando o incremento é realizada em concatenação com outras operações em que as operações de precedência é aplicada (
i++*2
é diferente de++i*2
, mas(i++)*2
e(++i)*2
devolve o mesmo valor), em muitos casos, eles são intercambiáveis. Um exemplo clássico é a sintaxe do loop for:tem o mesmo efeito de
Regra para lembrar
Para não confundir os dois operadores, adotei esta regra:
Associe a posição do operador
++
em relação à variáveli
à ordem da++
operação em relação à atribuiçãoDisse em outras palavras:
++
antes dosi
meios, o incremento deve ser realizado antes da atribuição;++
após oi
incremento dos meios deve ser realizado após a atribuição:fonte
Você pode pensar na conversão interna disso como várias instruções ;
você pode pensar assim,
você pode pensar assim,
fonte
a = i ++ significa a contém valor atual de i a = ++ i significa a contém valor incrementado de i
fonte
a = i++;
significa que o valor armazenadoa
será o valori
antes do incremento, mas 'sem incrementar' implica quei
não é incrementado, o que está completamente errado -i
é incrementado, mas o valor da expressão é o valor antes do incremento.Aqui está o exemplo para entender a diferença
saída:
10 12/11 11
(dependendo da ordem de avaliação dos argumentos para oprintf
função, que varia entre compiladores e arquiteturas)Explicação:
i++
->i
é impresso e, em seguida, é incrementado. (Imprime 10, masi
passa a 11)++i
-> oi
valor aumenta e imprime o valor. (Imprime 12 e o valori
também 12)fonte
i++
e++i