++nc vs nc = nc + 1

In K&R Ch 1:

The statement ++nc presents a new operator, ++, which means increment by one. You could instead write nc = nc + 1, but ++nc is more concise and often more efficient.

When would pre-increment be more efficient than the alternative? For most things, at least, the assembly for both is the add (edit: or inc) instruction. When do they differ?

1

5 Answers

That text is long out dated. It might have been true in the 70's that compilers would produce more efficient output for ++n, but not any more. All modern compilers will produce identical code.

5

For most things, at least, the assembly for both is the add instruction.

That's not quite true: there is often a separate "increment by one" instruction. However, that's irrelevant since any half-decent compiler will produce identical machine code for ++nc and nc = nc + 1.

In other words, there is no performance difference. There may have been when the book was written and compilers were not very good, but there isn't anymore.

I don't know for sure, I'm just thinking out aloud (maybe I shouldn't): Perhaps in K&R's time, ++nc was compiled into something more efficient than nc = nc + 1 (e.g., an increment instruction, rather than an addition). Nowadays, however, compilers probably optimise this automagically.

2

This is what I could see with gcc -S <filename>. I'll let you derive what you want!

> > cat 1.c #include <stdio.h> int main() { int i=0; ++i; return 0; } > > cat 2.c #include <stdio.h> int main() { int i=0; i++; return 0; } > > cat 3.c #include <stdio.h> int main(void) { int i=0; i = i + 1; return 0; } > > gcc -S 1.c 2.c 3.c > > > diff 1.s 2.s 1c1 < .file "1.c" --- > .file "2.c" > > diff 2.s 3.s 1c1 < .file "2.c" --- > .file "3.c" > > diff 3.s 1.s 1c1 < .file "3.c" --- > .file "1.c" > > 

The below is the content of the .s file for 1.c and the instructions are identical when compared with 2.s and 3.s!

> cat 1.s .file "1.c" .text .globl main .type main, @function main: .LFB2: pushq %rbp .LCFI0: movq %rsp, %rbp .LCFI1: movl $0, -4(%rbp) addl $1, -4(%rbp) movl $0, %eax leave ret .LFE2: .size main, .-main .section .eh_frame,"a",@progbits .Lframe1: .long .LECIE1-.LSCIE1 .LSCIE1: .long 0x0 .byte 0x1 .string "zR" .uleb128 0x1 .sleb128 -8 .byte 0x10 .uleb128 0x1 .byte 0x3 .byte 0xc .uleb128 0x7 .uleb128 0x8 .byte 0x90 .uleb128 0x1 .align 8 .LECIE1: .LSFDE1: .long .LEFDE1-.LASFDE1 .LASFDE1: .long .LASFDE1-.Lframe1 .long .LFB2 .long .LFE2-.LFB2 .uleb128 0x0 .byte 0x4 .long .LCFI0-.LFB2 .byte 0xe .uleb128 0x10 .byte 0x86 .uleb128 0x2 .byte 0x4 .long .LCFI1-.LCFI0 .byte 0xd .uleb128 0x6 .align 8 .LEFDE1: .ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)" .section .note.GNU-stack,"",@progbits > 

For "normal" variables there should be no difference as other answers suggest. Only if nc is voloatile qualified the result could be different. For such a variable the +1 form must first evaluate the expression nc that is load nc and then perform the addition. For the ++ form the compiler still could take shortcuts and increment the variable in place.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like