4

I was trying to think of a quick and illustrative way to generate a non-successful exit status and thought dividing by zero with the bc would be a good idea.

I was suprised to discover that although it does generate a runtime error, the exit status is still 0:

$ echo 41 + 1 | bc
42
$ echo $?
0
$ echo 42/0 | bc
Runtime error (func=(main), adr=6): Divide by zero
$ echo $?
0
  • Why does the bc utility not fail with a non-zero exit status?

Note: For a quick non-zero exit status I'm using return 1

Also, from shell-tips:

$ expr 1 / 0
expr: division by zero
$ echo $?
2
2
  • I would use ls nosuchfile for the illustration, by the way. Or if I want to show how non-zero exit statuses do have conventional meanings, I would set up as follows: echo hello > file1; echo hello > file2; echo goodbye > file3 and then show the exit status for cmp file1 file2, cmp file1 file3, cmp file1 file4.
    – Wildcard
    Commented Apr 4, 2017 at 0:22
  • You cannot devide by 0? The answer is unlimited?
    – Xorifelse
    Commented Apr 4, 2017 at 0:23

2 Answers 2

7

bc implementations differ a bit in their return status, but the general idea is that if you supply valid input then bc exits with the status 0. 42/0 is valid input: there's no read error, and it's even a syntactically valid expression, so bc returns 0. If you passed a second line with another operation, bc would perform it. This is different from expr whose purpose is to evaluate a single arithmetic expression; here the outcome of that single expression determines the return status.

The most straightforward way to generate an exit status that indicates failure is to call false. Things like expr 1 / 0 only have their place in obfuscated programming contests.

6

Look in the spec; this is expected behavior.

All of the input was read correctly by bc, so it produced exit status 0.

If you run bc on a non-existent file, like bc nosuchfile, you will get some other exit status.


For illustrating a non-zero exit status, I would either compare ls somefile and ls nosuchfile, or I would show how exit statuses 1 and 2 are conventionally used (1 for expected error or failure status, 2 for unexpected error) like so:

$ echo hello > file1
$ echo hello > file2
$ echo goodbye > file3
$ cmp -s file1 file2
$ echo $?
0
$ cmp -s file1 file3
$ echo $?
1
$ cmp -s file1 file4
$ echo $?
2
$ 
4
  • Also note: pubs.opengroup.org/onlinepubs/9699919799/utilities/…
    – user367890
    Commented Apr 4, 2017 at 1:12
  • 1
    @user367890, yes, thanks. I considered adding that to the answer but decided against it, since ultimately it just says, "The reasons are historical." But I will comment that POSIX formalizes what is already standard in practice: requiring behavior different from that of all existing implementations isn't the goal, even if it that behavior might seem like a better design. So "historical reasons" actually describes much of POSIX.
    – Wildcard
    Commented Apr 4, 2017 at 1:18
  • 2
    It is accepted behaviour, but not mandated nor recommended (so I wouldn't put expected here). The exit status is unspecified if there's an error. Here, regardless of POSIX conformance, in the case of GNU bc, I'd argue it's a bug as upon that division by zero (but also upon syntax error), it's a fatal error, bc doesn't process further input. Commented Apr 5, 2017 at 8:24
  • @Wildcard: Yes, but a non zero exit code does not indicate there was a failure reading – it could, but an implementation could also exit with <> 0 on for example n / 0. As the Q is “Why does bc exit 0 when dividing by 0?” – one should likely point out that this is an invalid statement. From how I read it, even failure to read input file could also result in exit code 0 as it is unspecified. Perhaps I am wrong.
    – user367890
    Commented Apr 5, 2017 at 22:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .