Em C, qual é a diferença entre using ++i
e i++
, e qual deve ser usada no bloco de incremento de um for
loop?
Em C, qual é a diferença entre using ++i
e i++
, e qual deve ser usada no bloco de incremento de um for
loop?
Respostas:
++i
aumentará o valor de i
e retornará o valor incrementado.
i = 1;
j = ++i;
(i is 2, j is 2)
i++
aumentará o valor de i
, mas retornará o valor original que era i
mantido antes de ser incrementado.
i = 1;
j = i++;
(i is 2, j is 1)
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
sobre i++
" e você não errará.
Há alguns comentários sobre a eficiência de ++i
e i++
. 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.
for(int i=0; i<10; i++){ print i; }
isso não será diferente do que for(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++
e print i
esteja em declarações diferentes, mas porque i++;
e i<10
está. A observação de @ jonnyflash não é tão estranha assim. Suponha que você tenha for(int i=0; i++<10){ print i; }
e for(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 incrementa i
o valor de 1 após o término da operação.
Vamos ver o seguinte exemplo:
int i = 1, j;
j = i++;
Aqui valor de j = 1
mas i = 2
. Aqui o valor de i
será atribuído j
primeiro e depois i
será incrementado.
++i
++i
é pré-incremento porque incrementa i
o valor de 1 antes da operação. Isso significa que j = i;
será executado depois i++
.
Vamos ver o seguinte exemplo:
int i = 1, j;
j = ++i;
Aqui valor de j = 2
mas i = 2
. Aqui o valor de i
será atribuído j
após o i
incremento de i
. Da mesma forma ++i
será executado antes j=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
for(i=0; i<5; i++)
printf("%d ",i);
E
for(i=0; i<5; ++i)
printf("%d ",i);
Ambos os loops produzirão a mesma saída. ie 0 1 2 3 4
.
Só importa onde você está usando.
for(i = 0; i<5;)
printf("%d ",++i);
Nesse caso, a saída será 1 2 3 4 5
.
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.
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.
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ído
Abaixo está a visualização da imagem e também aqui está um bom vídeo prático que demonstra o mesmo.
O motivo ++i
pode ser um pouco mais rápido do i++
que o i++
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
.
i
que o valor 1 quando você escreve uma instrução 1;
.
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".
Ambos incrementam o número. ++i
é equivalente a i = 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:
int i = 1;
int x = i++; //x is 1, i is 2
int y = ++i; //y is 3, i is 3
++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 de i
antes de incrementar o loop for. Mas, dependendo da lógica do seu programa, isso pode variar.
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:
for (int i = 0; i != X; ++i) ...
A diferença pode ser entendida por este código C ++ simples abaixo:
int i, j, k, l;
i = 1; //initialize int i with 1
j = i+1; //add 1 with i and set that as the value of j. i is still 1
k = i++; //k gets the current value of i, after that i is incremented. So here i is 2, but k is 1
l = ++i; // i is incremented first and then returned. So the value of i is 3 and so does l.
cout << i << ' ' << j << ' ' << k << ' '<< l << endl;
return 0;
A principal diferença é
- Postagem do i ++ ( após incremento ) e
++ i Pré ( Antes do Incremento )
- postar se
i =1
o loop aumentar como1,2,3,4,n
- pré se
i =1
o loop aumentar como2,3,4,5,n
Este pequeno código pode ajudar a visualizar a diferença de um ângulo diferente das respostas já postadas:
int i = 10, j = 10;
printf ("i is %i \n", i);
printf ("i++ is %i \n", i++);
printf ("i is %i \n\n", i);
printf ("j is %i \n", j);
printf ("++j is %i \n", ++j);
printf ("j is %i \n", j);
O resultado é:
//Remember that the values are i = 10, and j = 10
i is 10
i++ is 10 //Assigns (print out), then increments
i is 11
j is 10
++j is 11 //Increments, then assigns (print out)
j is 11
Preste atenção às situações antes e depois.
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:
int i, j;
for (i = 0; i <= 3; i++)
printf (" > iteration #%i", i);
printf ("\n");
for (j = 0; j <= 3; ++j)
printf (" > iteration #%i", j);
O resultado é:
> iteration #0 > iteration #1 > iteration #2 > iteration #3
> iteration #0 > iteration #1 > iteration #2 > iteration #3
Não sei você, mas não vejo diferença em seu uso, pelo menos em um loop for.
O seguinte fragmento de código C ilustra a diferença entre os operadores de pré e pós incremento e decremento:
int i;
int j;
Operadores de incremento:
i = 1;
j = ++i; // i is now 2, j is also 2
j = i++; // i is now 3, j is 2
Pré-incremento significa incremento na mesma linha. Pós-incremento significa incremento após a execução da linha.
int j=0;
System.out.println(j); //0
System.out.println(j++); //0. post-increment. It means after this line executes j increments.
int k=0;
System.out.println(k); //0
System.out.println(++k); //1. pre increment. It means it increments first and then the line executes
Quando se trata de operadores OR, AND, torna-se mais interessante.
int m=0;
if((m == 0 || m++ == 0) && (m++ == 1)) { //false
/* in OR condition if first line is already true then compiler doesn't check the rest. It is technique of compiler optimization */
System.out.println("post-increment "+m);
}
int n=0;
if((n == 0 || n++ == 0) && (++n == 1)) { //true
System.out.println("pre-increment "+n); //1
}
Na matriz
System.out.println("In Array");
int[] a = { 55, 11, 15, 20, 25 } ;
int ii, jj, kk = 1, mm;
ii = ++a[1]; // ii = 12. a[1] = a[1] + 1
System.out.println(a[1]); //12
jj = a[1]++; //12
System.out.println(a[1]); //a[1] = 13
mm = a[1];//13
System.out.printf ( "\n%d %d %d\n", ii, jj, mm ) ; //12, 12, 13
for (int val: a) {
System.out.print(" " +val); //55, 13, 15, 20, 25
}
Em C ++ pós / pré-incremento da variável ponteiro
#include <iostream>
using namespace std;
int main() {
int x=10;
int* p = &x;
std::cout<<"address = "<<p<<"\n"; //prints address of x
std::cout<<"address = "<<p<<"\n"; //prints (address of x) + sizeof(int)
std::cout<<"address = "<<&x<<"\n"; //prints address of x
std::cout<<"address = "<<++&x<<"\n"; //error. reference can't re-assign because it is fixed (immutable)
}
Em breve:
++i
e i++
funciona da mesma maneira se você não estiver gravando em uma função. Se você usar algo como function(i++)
oufunction(++i)
pode ver a diferença.
function(++i)
diz o primeiro incremento i em 1, depois disso, coloque isso i
na função com novo valor.
function(i++)
diz colocar primeiro i
na função após esse incremento i
em 1.
int i=4;
printf("%d\n",pow(++i,2));//it prints 25 and i is 5 now
i=4;
printf("%d",pow(i++,2));//it prints 16 i is 5 now
int j = ++i;
e int 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:
#include<stdio.h>
int main(int argc, char* argv[])
{
unsigned int i=0, a;
a = i++;
printf("i before: %d; value returned by i++: %d, i after: %d\n", i, a, i);
i=0;
a = ++i;
printf("i before: %d; value returned by ++i: %d, i after: %d\n", i, a, i);
}
A saída é:
i before: 1; value returned by i++: 0, i after: 1
i before: 1; value returned by ++i: 1, i after: 1
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, o i
valor será incrementado.
Outro exemplo:
#include<stdio.h>
int main ()
int i=0;
int a = i++*2;
printf("i=0, i++*2=%d\n", a);
i=0;
a = ++i * 2;
printf("i=0, ++i*2=%d\n", a);
i=0;
a = (++i) * 2;
printf("i=0, (++i)*2=%d\n", a);
i=0;
a = (++i) * 2;
printf("i=0, (++i)*2=%d\n", a);
return 0;
}
Resultado:
i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2
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:
for(int i=0; i<10; i++)
tem o mesmo efeito de
for(int i=0; i<10; ++i)
Para não confundir os dois operadores, adotei esta regra:
Associe a posição do operador ++
em relação à variável i
à ordem da ++
operação em relação à atribuição
Disse em outras palavras:
++
antes dos i
meios, o incremento deve ser realizado antes da atribuição;++
após o i
incremento dos meios deve ser realizado após a atribuição:Você pode pensar na conversão interna disso como várias instruções ;
i++;
você pode pensar assim,
i;
i = i+1;
++i;
você pode pensar assim,
i = i+i;
i;
a = i ++ significa a contém valor atual de i a = ++ i significa a contém valor incrementado de i
a = i++;
significa que o valor armazenado a
será o valor i
antes do incremento, mas 'sem incrementar' implica que i
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
int i=10;
printf("%d %d",i++,++i);
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, mas i
passa a 11)
++i
-> o i
valor aumenta e imprime o valor. (Imprime 12 e o valor i
também 12)
i++
e++i