++ nc vs nc = nc + 1

In K & R Ch 1:

The ++nc statement introduces the new ++ operator, which means incrementing by one. Instead, you can write nc = nc + 1 , but ++nc is shorter and often more efficient.

When will pre-growth be more effective than an alternative? For most things, at least the assembly for both is the add command (edit: or inc ). When do they differ?

+4
source share
5 answers

This text is out of date. In the 70s, it might be true that compilers would produce more efficient output for ++ n, but nothing more. All modern compilers will generate identical code.

+10
source

For most things, at least the build for both is the add command.

This is not entirely true: often there is a separate command "increment by one" . However, this does not matter, since any semi-decent compiler will generate the same machine code for ++nc and nc = nc + 1 .

In other words, there is no performance difference. Perhaps when the book was written, and the compilers were not very good, but it is no more.

+3
source

I don’t know for sure, I just out loud (maybe I shouldn't): maybe in K & R time ++nc was compiled into something more efficient than nc = nc + 1 (for example, an increment, not an addition). However, compilers are currently probably optimizing this automatically.

+2
source

This is what I could see with gcc -S <filename> . I will let you get 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" > > 

Below is the contents of the .s file for 1.c , and the instructions are identical compared to 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 > 
+1
source

There should be no differences for β€œnormal” variables, as other answers suggest. Only if nc matches voloatile can the result be different. For such a variable, form +1 must first evaluate the expression nc , that is, load nc , and then perform the addition. For form ++ compiler can still use shortcuts and increment the variable in place.

+1
source

Source: https://habr.com/ru/post/1387705/


All Articles