What's the difference between while(--i); and while(i) --i;? [closed]












0














My first submission of 61.Rotate List ran for 16 ms and I was not happy with that. So I changed this part of my code



k += 1;
while (--k) {
p = p->next;
}


to



while (k) {
p = p->next;
--k;
}


and then magic happened. Runtime decreased to 8 ms.



So what's the difference between them? Why the runtime gap is so large?










share|improve this question















closed as unclear what you're asking by gsamaras, Killzone Kid, Fantastic Mr Fox, AbcAeffchen, Ville-Valtteri Nov 20 '18 at 12:53


Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.











  • 5




    You mean besides when k is decremented?
    – Some programmer dude
    Nov 20 '18 at 9:16






  • 1




    And please read about how to ask good questions, as well as this question checklist. Lastly please try to create an Minimal, Complete, and Verifiable example to show us.
    – Some programmer dude
    Nov 20 '18 at 9:17






  • 1




    These codes are equivalent, unless k+=1 causes integer overflow
    – M.M
    Nov 20 '18 at 9:19








  • 7




    I wouldn’t use leetcode to judge efficiency of your code if I were you
    – Killzone Kid
    Nov 20 '18 at 9:21






  • 1




    G++ sees no difference with -O1. Did you forget to toggle code optimization when doing bench-marking?
    – felix
    Nov 20 '18 at 9:26
















0














My first submission of 61.Rotate List ran for 16 ms and I was not happy with that. So I changed this part of my code



k += 1;
while (--k) {
p = p->next;
}


to



while (k) {
p = p->next;
--k;
}


and then magic happened. Runtime decreased to 8 ms.



So what's the difference between them? Why the runtime gap is so large?










share|improve this question















closed as unclear what you're asking by gsamaras, Killzone Kid, Fantastic Mr Fox, AbcAeffchen, Ville-Valtteri Nov 20 '18 at 12:53


Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.











  • 5




    You mean besides when k is decremented?
    – Some programmer dude
    Nov 20 '18 at 9:16






  • 1




    And please read about how to ask good questions, as well as this question checklist. Lastly please try to create an Minimal, Complete, and Verifiable example to show us.
    – Some programmer dude
    Nov 20 '18 at 9:17






  • 1




    These codes are equivalent, unless k+=1 causes integer overflow
    – M.M
    Nov 20 '18 at 9:19








  • 7




    I wouldn’t use leetcode to judge efficiency of your code if I were you
    – Killzone Kid
    Nov 20 '18 at 9:21






  • 1




    G++ sees no difference with -O1. Did you forget to toggle code optimization when doing bench-marking?
    – felix
    Nov 20 '18 at 9:26














0












0








0







My first submission of 61.Rotate List ran for 16 ms and I was not happy with that. So I changed this part of my code



k += 1;
while (--k) {
p = p->next;
}


to



while (k) {
p = p->next;
--k;
}


and then magic happened. Runtime decreased to 8 ms.



So what's the difference between them? Why the runtime gap is so large?










share|improve this question















My first submission of 61.Rotate List ran for 16 ms and I was not happy with that. So I changed this part of my code



k += 1;
while (--k) {
p = p->next;
}


to



while (k) {
p = p->next;
--k;
}


and then magic happened. Runtime decreased to 8 ms.



So what's the difference between them? Why the runtime gap is so large?







c++ while-loop post-increment pre-increment






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 20 '18 at 9:18

























asked Nov 20 '18 at 9:15









Liyin Shao

102




102




closed as unclear what you're asking by gsamaras, Killzone Kid, Fantastic Mr Fox, AbcAeffchen, Ville-Valtteri Nov 20 '18 at 12:53


Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.






closed as unclear what you're asking by gsamaras, Killzone Kid, Fantastic Mr Fox, AbcAeffchen, Ville-Valtteri Nov 20 '18 at 12:53


Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.










  • 5




    You mean besides when k is decremented?
    – Some programmer dude
    Nov 20 '18 at 9:16






  • 1




    And please read about how to ask good questions, as well as this question checklist. Lastly please try to create an Minimal, Complete, and Verifiable example to show us.
    – Some programmer dude
    Nov 20 '18 at 9:17






  • 1




    These codes are equivalent, unless k+=1 causes integer overflow
    – M.M
    Nov 20 '18 at 9:19








  • 7




    I wouldn’t use leetcode to judge efficiency of your code if I were you
    – Killzone Kid
    Nov 20 '18 at 9:21






  • 1




    G++ sees no difference with -O1. Did you forget to toggle code optimization when doing bench-marking?
    – felix
    Nov 20 '18 at 9:26














  • 5




    You mean besides when k is decremented?
    – Some programmer dude
    Nov 20 '18 at 9:16






  • 1




    And please read about how to ask good questions, as well as this question checklist. Lastly please try to create an Minimal, Complete, and Verifiable example to show us.
    – Some programmer dude
    Nov 20 '18 at 9:17






  • 1




    These codes are equivalent, unless k+=1 causes integer overflow
    – M.M
    Nov 20 '18 at 9:19








  • 7




    I wouldn’t use leetcode to judge efficiency of your code if I were you
    – Killzone Kid
    Nov 20 '18 at 9:21






  • 1




    G++ sees no difference with -O1. Did you forget to toggle code optimization when doing bench-marking?
    – felix
    Nov 20 '18 at 9:26








5




5




You mean besides when k is decremented?
– Some programmer dude
Nov 20 '18 at 9:16




You mean besides when k is decremented?
– Some programmer dude
Nov 20 '18 at 9:16




1




1




And please read about how to ask good questions, as well as this question checklist. Lastly please try to create an Minimal, Complete, and Verifiable example to show us.
– Some programmer dude
Nov 20 '18 at 9:17




And please read about how to ask good questions, as well as this question checklist. Lastly please try to create an Minimal, Complete, and Verifiable example to show us.
– Some programmer dude
Nov 20 '18 at 9:17




1




1




These codes are equivalent, unless k+=1 causes integer overflow
– M.M
Nov 20 '18 at 9:19






These codes are equivalent, unless k+=1 causes integer overflow
– M.M
Nov 20 '18 at 9:19






7




7




I wouldn’t use leetcode to judge efficiency of your code if I were you
– Killzone Kid
Nov 20 '18 at 9:21




I wouldn’t use leetcode to judge efficiency of your code if I were you
– Killzone Kid
Nov 20 '18 at 9:21




1




1




G++ sees no difference with -O1. Did you forget to toggle code optimization when doing bench-marking?
– felix
Nov 20 '18 at 9:26




G++ sees no difference with -O1. Did you forget to toggle code optimization when doing bench-marking?
– felix
Nov 20 '18 at 9:26












1 Answer
1






active

oldest

votes


















3














This is probably just a compiler quirk or a benchmarking error. Code segments that produce identical results under all circumstances should theoretically compile to the same assembly. Usually the compiler fails to optimize if parts of the code are obfuscated (eg in different translation units) or if the code segment is complex enough that the optimizer fails to see the equivalency.



In this particular case, there should be no problem. Indeed, GCC compiles these segments to the same assembly.



struct P {
P* next;
};

P* func1(unsigned int k, P* p) {
k += 1;
while (--k) {
p = p->next;
}
return p;
}

P* func2(unsigned int k, P* p) {
while (k) {
p = p->next;
--k;
}
return p;
}


The assembly output is



func1(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L2
.L3:
movq (%rax), %rax
subl $1, %edi
jne .L3
.L2:
ret
func2(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L10
.L11:
movq (%rax), %rax
subl $1, %edi
jne .L11
.L10:
ret


Jump labels aside, the assembly for those functions is identical. You can view it in godbolt here.






share|improve this answer























  • Well, the C++ code in each function is exactly the same.
    – Mike Borkland
    Nov 20 '18 at 12:15










  • @MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
    – patatahooligan
    Nov 20 '18 at 12:55


















1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3














This is probably just a compiler quirk or a benchmarking error. Code segments that produce identical results under all circumstances should theoretically compile to the same assembly. Usually the compiler fails to optimize if parts of the code are obfuscated (eg in different translation units) or if the code segment is complex enough that the optimizer fails to see the equivalency.



In this particular case, there should be no problem. Indeed, GCC compiles these segments to the same assembly.



struct P {
P* next;
};

P* func1(unsigned int k, P* p) {
k += 1;
while (--k) {
p = p->next;
}
return p;
}

P* func2(unsigned int k, P* p) {
while (k) {
p = p->next;
--k;
}
return p;
}


The assembly output is



func1(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L2
.L3:
movq (%rax), %rax
subl $1, %edi
jne .L3
.L2:
ret
func2(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L10
.L11:
movq (%rax), %rax
subl $1, %edi
jne .L11
.L10:
ret


Jump labels aside, the assembly for those functions is identical. You can view it in godbolt here.






share|improve this answer























  • Well, the C++ code in each function is exactly the same.
    – Mike Borkland
    Nov 20 '18 at 12:15










  • @MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
    – patatahooligan
    Nov 20 '18 at 12:55
















3














This is probably just a compiler quirk or a benchmarking error. Code segments that produce identical results under all circumstances should theoretically compile to the same assembly. Usually the compiler fails to optimize if parts of the code are obfuscated (eg in different translation units) or if the code segment is complex enough that the optimizer fails to see the equivalency.



In this particular case, there should be no problem. Indeed, GCC compiles these segments to the same assembly.



struct P {
P* next;
};

P* func1(unsigned int k, P* p) {
k += 1;
while (--k) {
p = p->next;
}
return p;
}

P* func2(unsigned int k, P* p) {
while (k) {
p = p->next;
--k;
}
return p;
}


The assembly output is



func1(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L2
.L3:
movq (%rax), %rax
subl $1, %edi
jne .L3
.L2:
ret
func2(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L10
.L11:
movq (%rax), %rax
subl $1, %edi
jne .L11
.L10:
ret


Jump labels aside, the assembly for those functions is identical. You can view it in godbolt here.






share|improve this answer























  • Well, the C++ code in each function is exactly the same.
    – Mike Borkland
    Nov 20 '18 at 12:15










  • @MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
    – patatahooligan
    Nov 20 '18 at 12:55














3












3








3






This is probably just a compiler quirk or a benchmarking error. Code segments that produce identical results under all circumstances should theoretically compile to the same assembly. Usually the compiler fails to optimize if parts of the code are obfuscated (eg in different translation units) or if the code segment is complex enough that the optimizer fails to see the equivalency.



In this particular case, there should be no problem. Indeed, GCC compiles these segments to the same assembly.



struct P {
P* next;
};

P* func1(unsigned int k, P* p) {
k += 1;
while (--k) {
p = p->next;
}
return p;
}

P* func2(unsigned int k, P* p) {
while (k) {
p = p->next;
--k;
}
return p;
}


The assembly output is



func1(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L2
.L3:
movq (%rax), %rax
subl $1, %edi
jne .L3
.L2:
ret
func2(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L10
.L11:
movq (%rax), %rax
subl $1, %edi
jne .L11
.L10:
ret


Jump labels aside, the assembly for those functions is identical. You can view it in godbolt here.






share|improve this answer














This is probably just a compiler quirk or a benchmarking error. Code segments that produce identical results under all circumstances should theoretically compile to the same assembly. Usually the compiler fails to optimize if parts of the code are obfuscated (eg in different translation units) or if the code segment is complex enough that the optimizer fails to see the equivalency.



In this particular case, there should be no problem. Indeed, GCC compiles these segments to the same assembly.



struct P {
P* next;
};

P* func1(unsigned int k, P* p) {
k += 1;
while (--k) {
p = p->next;
}
return p;
}

P* func2(unsigned int k, P* p) {
while (k) {
p = p->next;
--k;
}
return p;
}


The assembly output is



func1(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L2
.L3:
movq (%rax), %rax
subl $1, %edi
jne .L3
.L2:
ret
func2(unsigned int, P*):
movq %rsi, %rax
testl %edi, %edi
je .L10
.L11:
movq (%rax), %rax
subl $1, %edi
jne .L11
.L10:
ret


Jump labels aside, the assembly for those functions is identical. You can view it in godbolt here.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 20 '18 at 12:52

























answered Nov 20 '18 at 10:41









patatahooligan

1,430618




1,430618












  • Well, the C++ code in each function is exactly the same.
    – Mike Borkland
    Nov 20 '18 at 12:15










  • @MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
    – patatahooligan
    Nov 20 '18 at 12:55


















  • Well, the C++ code in each function is exactly the same.
    – Mike Borkland
    Nov 20 '18 at 12:15










  • @MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
    – patatahooligan
    Nov 20 '18 at 12:55
















Well, the C++ code in each function is exactly the same.
– Mike Borkland
Nov 20 '18 at 12:15




Well, the C++ code in each function is exactly the same.
– Mike Borkland
Nov 20 '18 at 12:15












@MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
– patatahooligan
Nov 20 '18 at 12:55




@MikeBorkland Thanks for pointing that out. I messed up when copy-pasting, but I fixed it now.
– patatahooligan
Nov 20 '18 at 12:55



Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

RAC Tourist Trophy