Pergunta

Em C, qual é a diferença entre usar ++i e i++, e que deve ser usado no bloco de incrementação de um for laço?

Foi útil?

Solução

  • ++i incrementará o valor de i, e, em seguida, retorne o valor incrementado.

     i = 1;
     j = ++i;
     (i is 2, j is 2)
    
  • i++ incrementará o valor de i, mas retorne o valor original que i mantida antes de ser incrementada.

     i = 1;
     j = i++;
     (i is 2, j is 1)
    

Para for loop, qualquer um funciona. ++i parece mais comum, talvez porque é isso que é usado em K&R.

De qualquer forma, siga a orientação "prefira ++i sobre i++" e você não vai errar.

Há alguns comentários sobre a eficiência do ++i e i++.Em qualquer compilador que não seja de projeto estudantil, 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 Em Freund notas, é diferente para um objeto C++, já que operator++() é uma função e o compilador não pode otimizar a criação de um objeto temporário para conter o valor intermediário.

Outras dicas

eu++ é conhecido como Pós-incremento enquanto ++eu é chamado Pré-incremento.

i++

i++ é pós-incremento porque incrementa ivalor de 1 após o término da operação.

Vejamos o seguinte exemplo:

int i = 1, j;
j = i++;

Aqui valor de j = 1 mas i = 2.Aqui valor de i será atribuído a j primeiro, então i será incrementado.

++i

++i é pré-incremento porque incrementa ivalor de 1 antes da operação.Isso significa j = i; será executado depois i++.

Vejamos o seguinte exemplo:

int i = 1, j;
j = ++i;

Aqui valor de j = 2 mas i = 2.Aqui valor de i será atribuído a j depois de i incremento de i.De forma similar ++i será executado antes j=i;.

Para sua pergunta qual deve ser usado no bloco de incrementação de um loop for? a resposta é: você pode usar qualquer um.não importa.Ele executará seu loop for mesmo não.de 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.ou seja 0 1 2 3 4.

Só importa onde você o está usando.

for(i = 0; i<5;)
    printf("%d ",++i);

Neste caso a saída será 1 2 3 4 5.

Por favor, não se preocupe com a "eficiência" (velocidade, na verdade) de qual delas é mais rápida.Hoje em dia temos compiladores que cuidam dessas coisas.Use aquele que fizer sentido, com base no que mostra mais claramente sua intenção.

++i incrementa o valor e depois o retorna.

i++ retorna o valor e depois 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 depois ocorre o incremento.

++i:Neste cenário primeiro o incremento é feito e depois o valor é atribuído

Abaixo está a visualização da imagem e também aqui está um bom vídeo prático o que demonstra o mesmo.

enter image description here

A razão ++i pode ser um pouco mais rápido do que i++ é aquele i++ pode exigir uma cópia local do valor de i antes de ser incrementado, enquanto ++i nunca faz.Em alguns casos, alguns compiladores irão otimizá-lo, 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, então seguiria o conselho de Ryan Fox:quando posso usar os dois, eu uso ++i.

O resultado efetivo do uso de qualquer um deles é idêntico.Em outras palavras, o loop fará exatamente a mesma coisa em ambos os casos.

Em termos de eficiência, poderia haver uma penalidade envolvida na escolha de i++ em vez de ++i.Em termos de especificação de linguagem, o uso do operador pós-incremento deve criar uma cópia extra do valor sobre o qual o operador está agindo.Isso pode ser uma fonte de operações extras.

Entretanto, você deve considerar dois problemas principais com a lógica anterior.

  1. 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 ambos os métodos para o mesmo código eficiente.Se usar pós-incremento em vez de pré-incremento realmente fizer com que seu programa tenha um tempo de execução mais lento, então você está usando um Terrível compilador.

  2. Em termos de complexidade de tempo operacional, 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á enormemente ofuscada pela execução do corpo do loop.Em outras palavras, é muito melhor se preocupar em otimizar o código no loop do que no incremento.

Na minha opinião, toda a questão se resume simplesmente 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 aprendi antes de saber qualquer coisa sobre otimização.

Este é um exemplo por excelência de otimização prematura, e questões como essa têm o potencial de nos distrair de problemas sérios de design.Contudo, ainda é uma boa pergunta a ser feita, 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 semelhantes, mas não exatamente iguais.Ambos incrementam o número, mas ++i incrementa o número antes que a expressão atual seja avaliada, enquanto i++ incrementa o número depois que a expressão é 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 de prefixo):Incrementa e depois atribui o valor
(por exemplo): int i = 5, int b = ++iNesse caso, 6 é atribuído primeiro a b e depois aumenta para 7 e assim por diante.

i++ (Operação Postfix):Atribui e depois incrementa o valor
(por exemplo): int i = 5, int b = i++Nesse caso, 5 é atribuído primeiro a b e depois aumenta para 6 e assim por diante.

Caso de loop for: i++ é usado principalmente porque, normalmente usamos o valor inicial de i antes de incrementar no loop for.Mas dependendo da lógica do seu programa isso pode variar.

++i:é pré-incremento e o outro é pós-incremento.

i++:obtém o elemento e depois o incrementa.
++i:incrementa i e então retorna o elemento.

Exemplo:

int i = 0;
printf("i: %d\n", i);
printf("i++: %d\n", i++);
printf("++i: %d\n", ++i);

Saída:

i: 0
i++: 0
++i: 2

Suponho que você entenda a diferença de semântica agora (embora sinceramente me pergunto por que as pessoas perguntam 'o que o operador X significa' as perguntas sobre o excesso de pilha em vez de ler, você sabe, um livro ou um tutorial da web ou algo assim.

Mas, de qualquer forma, até onde se usar, ignore 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 precisa do valor antes do incremento em sua instrução, não use essa forma do operador.É uma questão menor, mas, a menos que você esteja trabalhando com um guia de estilo que proíbe uma versão a favor do outro (também conhecido como um guia de estilo de cabeça de osso), você deve usar o formulário que mais expressa exatamente o que 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 é

  • i++ Postar(Após o incremento) e
  • ++i Pré (Antes do incremento)

    • postar se i =1 o loop aumenta como 1,2,3,4,n
    • pré se i =1 o loop aumenta como 2,3,4,5,n

eu++ e ++eu

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.

para loop

Quanto a qual deles deve ser usado em um bloco de incrementação 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 sobre você, mas não vejo nenhuma diferença no 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é-cremento 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, fica 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
}

Em 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 de 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 forma se você não os estiver escrevendo em uma função.Se você usar algo como function(i++) ou function(++i) Você pode ver a diferença.

function(++i) diz primeiro incremento i em 1, depois coloque isso i na função com novo valor.

function(i++) diz coloque primeiro i na função após esse incremento i por 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

A única diferença é a ordem das operações entre o incremento da variável e o valor retornado pelo operador.

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 depois de incrementado, enquanto ++i retorne o valor antes de ser incrementado.No final, em ambos os casos, o i terá seu valor 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;
}

Saída:

i=0, i++*2=0
i=0, ++i*2=2
i=0, (++i)*2=2
i=0, (++i)*2=2

Muitas vezes não há diferença

As diferenças ficam claras quando o valor retornado é atribuído a outra variável ou quando o incremento é realizado em concatenação com outras operações onde a precedência de operações é aplicada (i++*2 é diferente de ++i*2, mas (i++)*2 e (++i)*2 retorna 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)

Regra para lembrar

Para não fazer confusão entre as duas operadoras adotei esta regra:

Associe a posição do operador ++ em relação à variável i à ordem do ++ operação em relação à atribuição

Dito em outras palavras:

  • ++ antes i significa que o incremento deve ser realizado antes atribuição;
  • ++ depois i significa que o incremento deve ser realizado depois atribuição:

Você pode pensar na conversão interna disso como um múltiplas declarações;

// case 1 :

i++;

/* you can think as,
 * i;
 * i= i+1;
 */

// case 2

++i;

/* you can think as,
 * i = i+i;
 * i;
 */

a = i ++ significa que a contém o valor de I Value a = ++ I significa que um contém o valor incrementado

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 o printf função, que varia entre compiladores e arquiteturas)

Explicação:i++->i é impresso e, em seguida, incrementa.(Imprime 10, mas i se tornará 11)++i->i o valor aumenta e imprime o valor.(Imprime 12, e o valor de i também 12)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top