收录日期:2019/04/20 17:04:30 时间:2010-06-22 20:53:07 标签:c

Below is a code which I am not understand.

#include<stdio.h>

int main(int argc, char *argv[])
{
      int num;

      printf("\n Number: " );
      scanf("%d", &num);

      if (num >= 0)
      {
           int abs = num;
      }
      else
      {
            int abs = -num;
      }

      {
          int abs;
          printf("\n Values are %d %d", num ,abs);
       }
      return 0;
}

When I enter a number as 4, the output is Values are 4 4
When I enter a number as -4, the output is Values are -4 4

I am not able to understand how is it able to print the absolute value?. the variable abs defined in the if loop and else loop should have been deallocated after exiting.

Kindly let me know.

Regards, darkie

Hilarious code.

It relies on the fact that all three definitions of abs will be allocated on the same place on the stack, due to compiler optimization.

The third abs has to be random garbag, the garbage turns out to be the result of the previous variable with the same name (the name would not matter).

You are absolutely correct.

Do you see the last block where int abs is declared that last time? Notice that abs is not initialized, and using uninitialized variables yields undefined results. With your particular compiler, it just happens that you luck out, and block of memory where the new abs sits still contains the result from it's (expired) previous scope.

These variables are allocated on the stack yet you didn't modify it, I mean you didn't get out of the function, so yet, programmatically you'll get a "new" 'abs' int in the last code block, but in reality, this "new" 'abs' int is in the place where the old 'abs' was (on the STACK!), thus, its default value is the same.

That's called "undefined behavior".

You're getting "stack trash" when you declare the abs with the printf.

It works like this:

if (num >= 0) {
  create 'abs' at memory address N, put 'num' in it.
  destroy 'abs' // but leave the 'garbage' at memory address N
} else {
  create 'abs' at memory address N, put '-num' in it.
  destroy 'abs' // but leave the 'garbage' at memory address N
}

{
  create 'abs' at memory address N, don't put anything in it.
  // your compiler has decided it will reuse N.  That's a valid choice.
  // your compiler has decided it will not zero the memory at address N.  That's valid.
  read whatever was at 'abs'.  // it's whatever was assigned in the conditional.
}

Always compile with -Wall :)

You're using an uninitialized value of abs in the printf. The C language standard doesn't require it to be anything in particular because it's uninitialized. It could be 0, or 1, or -32765

In this particular case, you're probably getting the same number because the compiled code is reusing a register for the temporary values of abs, and that same register again for your abs variable in the printf block.

You can look at the disassembly code to see exactly what the compiler is doing in terms of machine instructions.