2

We were having a quiz of sorts and had the following question where we had to find the error, or if there's none, the output of the given code:

#include <stdio.h>

int main(void) {
  int n = 012;

  b: printf("%d\n",n--);

  if(n!=0){
    n--;
    goto b;
  }
  
  return 0;
}

I don't see anything wrong with this in theory but this leads to an infinite loop with the variable going way below 0. Could anyone help me with this?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Chronos_27
  • 21
  • 1
  • 3
    What did you learn debugging? Did you intend to decrement `n` in two places? – Stephen Newell Dec 31 '20 at 03:13
  • 1
    Use paper and pencil to step through the code and track the value of `n`. It will only take a minute. You'll see why the test `n != 0` doesn't stop the looping. Note that the literal `012` is an **octal** value. – Blastfurnace Dec 31 '20 at 03:17
  • Why are you using `goto`? See https://stackoverflow.com/questions/46586/goto-still-considered-harmful – Ed Heal Dec 31 '20 at 03:32
  • iteration will print n for indexes, 10,8,6,4,2,0 , after print inside printf we are decrementing the n by 1. when n reach if statement , it will be 9, 7,5,3,1,-1. and the termination condition n==0 will never hit. if the intention is to print "10,8,6,4,2,0 " , change the termination condition from " if(n!=0){ " to "if(n>0){". – Nishad C M Dec 31 '20 at 03:36
  • @EdHeal: Learn `goto` so you can use it. Error handling in C without `goto` is not fun. – Joshua Dec 31 '20 at 03:38
  • @Joshua - In my career as a C programmer I never need to use `goto` for error handling. Some of those were complex systems (e.g. for a power station) – Ed Heal Dec 31 '20 at 03:44
  • @EdHeal: How do you handle multiple cleanup steps and multiple failure points? – Joshua Dec 31 '20 at 03:50
  • 1
    Use of early returns from a function, if statements. There are plenty of techniques that do not require `goto` and I would submit that these techniques make it easier to ensure that the code is correct. One reason (and a very good one IMHO) is answering the question "how did you get to the goto label?) Might be easy to answer when the code is written but after a long period of maintenance it gets harder to check. – Ed Heal Dec 31 '20 at 03:56
  • The takeaway from the "quiz" is: never write code like that! – koder Dec 31 '20 at 11:15

6 Answers6

1

You should only have one n-- statement. otherwise even if it reaches 0, when it get the first n-- it will be decremented one more time and will become -1. (so it will never match 0).

Hence, please change your code to

#include <stdio.h>

int main(void) {
  int n = 012;

  b: printf("%d\n",n--);

  if(n!=0){
   goto b;
  }
  
  return 0;
}
Ken Lee
  • 6,985
  • 3
  • 10
  • 29
1
#include <stdio.h>

int main(void) {
  int n = 012;

  b: printf("%d\n",n);

  if(n!=0){
    n--;
    goto b;
  }
  
  return 0;
}

This would work. The version you posted does not work because it will never get to 0. It is subtracting once in the if statement, and once in the printf.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
PurpSchurp
  • 581
  • 5
  • 14
1

The condition if (n != 0) is always getting satisfied.

On each iteration the number n decreases by 2.

So when n = 2, it gets decremented once after printf("%d\n",n--)

then the condition if (n != 0) is true, as n = 1

Inside the condition block n is decremented once again, n = 0

So the next time before reaching the condition if (n != 0), n equals to -1,

which leads to an infinite loop.

shb
  • 5,957
  • 2
  • 15
  • 32
  • As n is decremented twice, the if condition only sees odd numbers when n starts out as even number. If n starts out as an odd number, the if condition only sees even numbers and the iteration ends. – koder Dec 31 '20 at 11:14
0

In C 012 is an octal base number, in decimal it is equal to 10.

This code:

#include <stdio.h>

int main(void) {
  int n = 012;

  b: printf("%d\n",n--);

  if(n!=0){
    n--;
    goto b;
  }
  
  return 0;
}

Does this:

print n (10)
subtract 1 of n (n = 10 - 1 = 9)
check if n != 0 (9 != 0 -> true)
subtract 1 of n (n = 9 - 1 = 8)
jump to b

print n (8)
subtract 1 of n (n = 8 - 1 = 7)
check if n != 0 (7 != 0 -> true)
subtract 1 of n (n = 7 - 1 = 6)
jump to b

print n (6)
subtract 1 of n (n = 6 - 1 = 5)
check if n != 0 (5 != 0 -> true)
subtract 1 of n (n = 5 - 1 = 4)
jump to b

print n (4)
subtract 1 of n (n = 4 - 1 = 3)
check if n != 0 (3 != 0 -> true)
subtract 1 of n (n = 3 - 1 = 2)
jump to b

print n (2)
subtract 1 of n (n = 2 - 1 = 1)
check if n != 0 (1 != 0 -> true)
subtract 1 of n (n = 1 - 1 = 0)
jump to b

print n (0)
subtract 1 of n (n = 0 - 1 = -1)
check if n != 0 (-1 != 0 -> true)
subtract 1 of n (n = -1 - 1 = -2)
jump to b

print n (-2)
...
...
... goes on infinitely

Note that when n will never equal to 0 when the program checks if n != 0, because in this evaluation n is always an odd number since two subtractions by 1 are made every time.

isrnick
  • 621
  • 5
  • 12
0

Change from b: printf("%d\n",n--); to b: printf("%d\n",n);.

or

Change from

  if(n!=0){
    n--;
    goto b;

to

  if(n!=0){
    n;
    goto b;

Because n-- equals n = n - 1.

Your program:

#include <stdio.h>

int main(void) {
  int n = 012;

  b: printf("%d\n",n--); // n = n - 1

  if(n!=0){
    n--; // n = n - 1
    goto b;
  }
  
  return 0;
}
Itati
  • 193
  • 11
0

for out put [10, 8, 6, 4,2, 0]

    #include <stdio.h>

    int main(void) {
      int n = 012;

      b: printf("%d\n",n--);

      if(n>0){
        n--;
        goto b;
      }

      return 0;
    }

for [10,9,8,7,6,5,4,3,2,1]

    #include <stdio.h>

    int main(void) {
      int n = 012;

      b: printf("%d\n",n--);

      if(n>0){
        //n--;
        goto b;
      }

      return 0;
    }
Nishad C M
  • 142
  • 6