-3

i want to know if increment/decrement operator results vary from compiler to compiler or it is independent of the compiler. as I am getting different results in different compilers of c/c++ (tested in G++, TDM, gcc) for the same expression.

Vimlesh
  • 109
  • 1
  • 5
  • 3
    The compiler doesn't execute it. The machine code it generates will vary depending on the processor that it's compiling for. – Paul Aug 19 '14 at 22:20
  • 1
    The "exact way" is clearly going to depend on the compiler and the language. (And, to nitpick: the compiler doesn't "execute" any of the code it finds; it simply compiles it to an intermediate form for the linker to use later.) – Ken White Aug 19 '14 at 22:24
  • this is a useful tool for exploring what the compiler does to your code. http://gcc.godbolt.org/ just enter your code and it will show you the assembly code that gcc will generate. Remember to turn off optimizations if you want it to be an exact translation. – genisage Aug 19 '14 at 22:24
  • These operators can be overloaded in C++, I assume you are asking for built-in types (`int`, `float` ...) ? Your question should be more precise. – teh internets is made of catz Aug 19 '14 at 22:24
  • 1
    If you want to know the **exact way**, the only correct answer is to look at the source code for the compiler you care about. – merlin2011 Aug 19 '14 at 22:24

1 Answers1

4

Let's look at the internal llvm assembly. Which isn't hard to do.

C++ code:

void preincrement() __attribute__((noinline));
void preincrement() {
    volatile int x = 10;
    volatile int y = ++x;
}

void postincrement() __attribute__((noinline));
void postincrement() {
    volatile int x = 10;
    volatile int y = x++;
}

int main()
{
    preincrement();
    postincrement();
}

Resultant LLVM Assembly (minus some leading and trailing text that isn't interesting):

; Function Attrs: noinline nounwind uwtable
define void @_Z12preincrementv() #0 {
  %x = alloca i32, align 4
  %y = alloca i32, align 4
  store volatile i32 10, i32* %x, align 4
  %1 = load volatile i32* %x, align 4
  %2 = add nsw i32 %1, 1
  store volatile i32 %2, i32* %x, align 4
  store volatile i32 %2, i32* %y, align 4
  ret void
}

; Function Attrs: noinline nounwind uwtable
define void @_Z13postincrementv() #0 {
  %x = alloca i32, align 4
  %y = alloca i32, align 4
  store volatile i32 10, i32* %x, align 4
  %1 = load volatile i32* %x, align 4
  %2 = add nsw i32 %1, 1
  store volatile i32 %2, i32* %x, align 4
  store volatile i32 %1, i32* %y, align 4
  ret void
}

; Function Attrs: nounwind uwtable
define i32 @main() #1 {
  tail call void @_Z12preincrementv()
  tail call void @_Z13postincrementv()
  ret i32 0
}

We can see here pretty clearly the only difference: In the post increment version, we use the original value, instead of the upgraded value.

In both cases, we just use a traditional add opcode to do the real work.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173