Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #3162 > unrolled thread

Return value for error

Started bypozz <pozzugno@gmail.com>
First post2011-05-03 01:31 -0700
Last post2011-05-03 12:09 -0700
Articles 20 on this page of 30 — 19 participants

Back to article view | Back to comp.lang.c


Contents

  Return value for error pozz <pozzugno@gmail.com> - 2011-05-03 01:31 -0700
    Re: Return value for error jacob navia <jacob@spamsink.net> - 2011-05-03 10:46 +0200
    Re: Return value for error Ike Naar <ike@otaku.freeshell.org> - 2011-05-03 09:04 +0000
      Re: Return value for error Ian Collins <ian-news@hotmail.com> - 2011-05-03 21:19 +1200
    Re: Return value for error James Kuyper <jameskuyper@verizon.net> - 2011-05-03 06:26 -0400
      Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-03 12:03 -0700
        Re: Return value for error "Kleuskes & Moos" <kleuske@xs4all.nl> - 2011-05-04 05:15 -0700
          Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-04 08:26 -0700
            Re: Return value for error "Kleuskes & Moos" <kleuske@xs4all.nl> - 2011-05-04 17:08 -0700
              Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-04 17:54 -0700
                Re: Return value for error "Kleuskes & Moos" <kleuske@xs4all.nl> - 2011-05-05 12:03 -0700
    Re: Return value for error James Dow Allen <jdallen2000@yahoo.com> - 2011-05-03 03:45 -0700
      Re: Return value for error Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-05-03 20:50 +0000
    Re: Return value for error pete <pfiland@mindspring.com> - 2011-05-03 07:50 -0400
      Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-03 12:04 -0700
    Re: Return value for error Martin Ambuhl <mambuhl@earthlink.net> - 2011-05-03 07:59 -0400
    Re: Return value for error Mark Storkamp <mstorkamp@yahoo.com> - 2011-05-03 08:46 -0500
    Re: Return value for error Stephen Sprunk <stephen@sprunk.org> - 2011-05-03 10:13 -0500
      Re: Return value for error William Ahern <william@wilbur.25thandClement.com> - 2011-05-03 13:08 -0700
    Re: Return value for error Kenneth Brody <kenbrody@spamcop.net> - 2011-05-03 13:23 -0400
      Re: Return value for error Peter Nilsson <airia@acay.com.au> - 2011-05-03 16:01 -0700
      Re: Return value for error Nobody <nobody@nowhere.com> - 2011-05-05 07:21 +0100
        Re: Return value for error Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-05 15:13 +0100
          Re: Return value for error Nobody <nobody@nowhere.com> - 2011-05-06 03:51 +0100
            Re: Return value for error James Kuyper <jameskuyper@verizon.net> - 2011-05-05 23:38 -0400
        Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-05 08:44 -0700
          Re: Return value for error Seebs <usenet-nospam@seebs.net> - 2011-05-05 20:49 +0000
            Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-05 14:10 -0700
              Re: Return value for error Seebs <usenet-nospam@seebs.net> - 2011-05-06 00:26 +0000
    Re: Return value for error Keith Thompson <kst-u@mib.org> - 2011-05-03 12:09 -0700

Page 1 of 2  [1] 2  Next page →


#3162 — Return value for error

Frompozz <pozzugno@gmail.com>
Date2011-05-03 01:31 -0700
SubjectReturn value for error
Message-ID<e63ceea9-301d-4b90-9495-4e2a8085fae5@x1g2000yqb.googlegroups.com>
A very simple question. What do you use as the return value of a
function for error/ok results?
I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
for errors.

If !=0 is ok, I can write:

  if (myfunction()) printf("OK\n");

but I have only one error code (0), while, in some cases, it could be
useful to have more informations about the type of error.

If !=0 is error I can have several error codes, but I have to write

  if (!myfuction()) printf("OK\n");

that apparently seems myfunction has not terminated with success.

Another strategy is to define custom error code:

#define ERROR_OK  0
#define ERROR_UNDEFINED 1
#define ERROR_WRONGVALUE 2

and so on, and always write:

  if (myfuction() == ERROR_OK) printf("OK\n");

[toc] | [next] | [standalone]


#3163

Fromjacob navia <jacob@spamsink.net>
Date2011-05-03 10:46 +0200
Message-ID<ipofdd$e5k$1@speranza.aioe.org>
In reply to#3162
Le 03/05/11 10:31, pozz a écrit :
> A very simple question. What do you use as the return value of a
> function for error/ok results?
> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> for errors.
>
> If !=0 is ok, I can write:
>
>    if (myfunction()) printf("OK\n");
>
> but I have only one error code (0), while, in some cases, it could be
> useful to have more informations about the type of error.

Yes... That is the reason that option is not really useful.

>
> If !=0 is error I can have several error codes, but I have to write
>
>    if (!myfuction()) printf("OK\n");
>
> that apparently seems myfunction has not terminated with success.
>

I would recommend
      if (myfunction() == SUCCESS)

where SUCCESS is zero

> Another strategy is to define custom error code:
>
> #define ERROR_OK  0
> #define ERROR_UNDEFINED 1
> #define ERROR_WRONGVALUE 2
>
> and so on, and always write:
>
>    if (myfuction() == ERROR_OK) printf("OK\n");

The problem with "ERROR_OK" is that it is contradictory: An "OK error" ?

In the C containers library I decided (after much pondering) that:

Positive value: No error

Negative value: error code

Zero: Warning but OK.

For instance a function like POP(container) will return

< 0 if  container == NULL. This is a hard error.
Zero: container was empty. Maybe this isn't an error.

 >0 one element was popped. This means everything is OK.

if (Pop(container) < 0) {
      // error handling
}

Note that you can code other useful information  in positive values.
You could return the number of elements still remaining in the stack
for instance.

[toc] | [prev] | [next] | [standalone]


#3164

FromIke Naar <ike@otaku.freeshell.org>
Date2011-05-03 09:04 +0000
Message-ID<slrn3vfsirvh8s.dl3.ike@otaku.freeshell.org>
In reply to#3162
On 2011-05-03, pozz <pozzugno@gmail.com> wrote:
> A very simple question. What do you use as the return value of a
> function for error/ok results?
> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> for errors.
>
> If !=0 is ok, I can write:
>
>   if (myfunction()) printf("OK\n");
>
> but I have only one error code (0), while, in some cases, it could be
> useful to have more informations about the type of error.
>
> If !=0 is error I can have several error codes, but I have to write
>
>   if (!myfuction()) printf("OK\n");
>
> that apparently seems myfunction has not terminated with success.
>
> Another strategy is to define custom error code:
>
> #define ERROR_OK  0
> #define ERROR_UNDEFINED 1
> #define ERROR_WRONGVALUE 2
>
> and so on, and always write:
>
>   if (myfuction() == ERROR_OK) printf("OK\n");

Another improvement would be to drop the ``ERROR'' prefix from
the constants (``ERROR_OK'' is a contradictio in terminis, isn't it?)
and replace it with a prefix that indicates that the constant has to do
with a particular function.
This helps if your program has several functions that follow the same
strategy.

  #define FROBOZZ_OK  0
  #define FROBOZZ_UNDEFINED 1
  #define FROBOZZ_WRONGVALUE 2

  #define WHACK_OK  0
  #define WHACK_UNWHACKABLE 1
  #define WHACK_ALREADYWHACKED 2

  if (frobozz() == FROBOZZ_OK) printf("OK\n");
  if (whack() == WHACK_OK) printf("OK\n");

[toc] | [prev] | [next] | [standalone]


#3165

FromIan Collins <ian-news@hotmail.com>
Date2011-05-03 21:19 +1200
Message-ID<929vk4Fj03U11@mid.individual.net>
In reply to#3164
On 05/ 3/11 09:04 PM, Ike Naar wrote:
> On 2011-05-03, pozz<pozzugno@gmail.com>  wrote:
>> A very simple question. What do you use as the return value of a
>> function for error/ok results?
>> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
>> for errors.
>>
>> If !=0 is ok, I can write:
>>
>>    if (myfunction()) printf("OK\n");
>>
>> but I have only one error code (0), while, in some cases, it could be
>> useful to have more informations about the type of error.
>>
>> If !=0 is error I can have several error codes, but I have to write
>>
>>    if (!myfuction()) printf("OK\n");
>>
>> that apparently seems myfunction has not terminated with success.
>>
>> Another strategy is to define custom error code:
>>
>> #define ERROR_OK  0
>> #define ERROR_UNDEFINED 1
>> #define ERROR_WRONGVALUE 2
>>
>> and so on, and always write:
>>
>>    if (myfuction() == ERROR_OK) printf("OK\n");
>
> Another improvement would be to drop the ``ERROR'' prefix from
> the constants (``ERROR_OK'' is a contradictio in terminis, isn't it?)
> and replace it with a prefix that indicates that the constant has to do
> with a particular function.
> This helps if your program has several functions that follow the same
> strategy.
>
>    #define FROBOZZ_OK  0
>    #define FROBOZZ_UNDEFINED 1
>    #define FROBOZZ_WRONGVALUE 2

I prefer an enum to #defines.  It's more debugger friendly, less typing 
and gives you a type to return.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#3167

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-05-03 06:26 -0400
Message-ID<ipol8c$ohd$1@dont-email.me>
In reply to#3162
On 05/03/2011 04:31 AM, pozz wrote:
> A very simple question. What do you use as the return value of a
> function for error/ok results?
> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> for errors.
> 
> If !=0 is ok, I can write:
> 
>   if (myfunction()) printf("OK\n");

This is a perfectly reasonable approach, but when you use it, one of the
most important things is to make sure to name the function so that it
can be read as a question, and give it a non-zero value if the answer to
that question is "yes". Example from the C standard library: isalpha().
However, there's also lots of functions in the C standard library which
violate this rule; for instance, fseek().

If you can't think of a name for the function which would make this
work, then using this approach is probably not appropriate.

...
> Another strategy is to define custom error code:
> 
> #define ERROR_OK  0
> #define ERROR_UNDEFINED 1
> #define ERROR_WRONGVALUE 2
> 
> and so on, and always write:
> 
>   if (myfuction() == ERROR_OK) printf("OK\n");

If your code returns multiple different error codes, then somewhere you
should have a call to the function that actually does different things,
depending upon which error code is returned; a switch() is usually the
best way to do this. You can also have calls that don't make a
distinction; but if there aren't any calls to the function which do make
the distinction, then you don't really need to distinguish different
error conditions.

I'm guilty of violating that rule in my own code; but my intention is
that test drivers for the called routine will check which error code is
returned, even if the actual delivered program does not.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#3186

FromKeith Thompson <kst-u@mib.org>
Date2011-05-03 12:03 -0700
Message-ID<lnaaf3vc77.fsf@nuthaus.mib.org>
In reply to#3167
James Kuyper <jameskuyper@verizon.net> writes:
> On 05/03/2011 04:31 AM, pozz wrote:
>> A very simple question. What do you use as the return value of a
>> function for error/ok results?
>> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
>> for errors.
>> 
>> If !=0 is ok, I can write:
>> 
>>   if (myfunction()) printf("OK\n");
>
> This is a perfectly reasonable approach, but when you use it, one of the
> most important things is to make sure to name the function so that it
> can be read as a question, and give it a non-zero value if the answer to
> that question is "yes". Example from the C standard library: isalpha().

Right.  The important distinction here is that the result of isalpha()
is purely a yes/no result, *not* a success/failure result.  If isalpha()
could tell you either
    Yes, that's an alphabetic character
or
    No, that's not an alphabetic character
or
    Oops, I can't tell what that is
the it would need a different interface.  In fact, none of the is*()
functions have any way to indicate failure.

> However, there's also lots of functions in the C standard library which
> violate this rule; for instance, fseek().

I wouldn't say fseek() violates the rule, it just follows a different
one.  It attempts to perform an action (seeking to the specified
position) and returns a result indicating either that it succeeded, or
that it failed.  The common convention is to use 0 for success, non-0
for failure.  (It doesn't use different non-0 values to denote different
kinds of failure.)

> If you can't think of a name for the function which would make this
> work, then using this approach is probably not appropriate.

Agreed.  But even if the function answers a yes/no question, you still
have to think about cases where the question can't be answered.  Most
yes/no functions in the standard library don't have ways to indicate
errors (see is*(), feof(), ferror()).

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#3225

From"Kleuskes & Moos" <kleuske@xs4all.nl>
Date2011-05-04 05:15 -0700
Message-ID<c24039e1-19f0-41f5-8b24-4a645ed11004@24g2000yqk.googlegroups.com>
In reply to#3186
On May 3, 9:03 pm, Keith Thompson <ks...@mib.org> wrote:
> James Kuyper <jameskuy...@verizon.net> writes:
> > On 05/03/2011 04:31 AM, pozz wrote:
> >> A very simple question. What do you use as the return value of a
> >> function for error/ok results?
> >> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> >> for errors.
>
> >> If !=0 is ok, I can write:
>
> >>   if (myfunction()) printf("OK\n");
>
> > This is a perfectly reasonable approach, but when you use it, one of the
> > most important things is to make sure to name the function so that it
> > can be read as a question, and give it a non-zero value if the answer to
> > that question is "yes". Example from the C standard library: isalpha().
>
> Right.  The important distinction here is that the result of isalpha()
> is purely a yes/no result, *not* a success/failure result.  If isalpha()
> could tell you either
>     Yes, that's an alphabetic character
> or
>     No, that's not an alphabetic character
> or
>     Oops, I can't tell what that is
> the it would need a different interface.  In fact, none of the is*()
> functions have any way to indicate failure.

Perhaps that's got to do with the fact that they cannot actually fail.
Whatever the input, it's always possible to say wether it codes for an
letter, a number, upper or lower case character or not.

However, for functions that might actually fail, the consideration is
actually an important one.

[toc] | [prev] | [next] | [standalone]


#3231

FromKeith Thompson <kst-u@mib.org>
Date2011-05-04 08:26 -0700
Message-ID<lnoc3itrkz.fsf@nuthaus.mib.org>
In reply to#3225
"Kleuskes & Moos" <kleuske@xs4all.nl> writes:
> On May 3, 9:03 pm, Keith Thompson <ks...@mib.org> wrote:
[...]
>> Right.  The important distinction here is that the result of isalpha()
>> is purely a yes/no result, *not* a success/failure result.  If isalpha()
>> could tell you either
>>     Yes, that's an alphabetic character
>> or
>>     No, that's not an alphabetic character
>> or
>>     Oops, I can't tell what that is
>> the it would need a different interface.  In fact, none of the is*()
>> functions have any way to indicate failure.
>
> Perhaps that's got to do with the fact that they cannot actually fail.
> Whatever the input, it's always possible to say wether it codes for an
> letter, a number, upper or lower case character or not.

Well, sort of.  The argument of the is*() function is an int,
but its value is required to be representable as an unsigned char
or to be equal to EOF.  The standard *could* have specified some
kind of error handling for isalpha(UCHAR_MAX + 1), but instead it
just says the behavior is undefined.  Similarly, the behavior of
feof(FILE*(NULL)) is undefined.

The choice was between imposing a small burden on the caller to
avoid passing bad arguments, and making the interface substantially
more inconvenient.

> However, for functions that might actually fail, the consideration is
> actually an important one.

Right.  If you want to have a function that returns a yes/no result,
but the caller can't reliably avoid passing invalid arguments,
you might have it return an error code (zero for success, non-zero
for error) and pass the actual result via an int* argument.

(Languages with exception handling generally don't have this problem.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#3240

From"Kleuskes & Moos" <kleuske@xs4all.nl>
Date2011-05-04 17:08 -0700
Message-ID<6a2107db-6e19-41a8-aa82-616cc2caa6aa@c41g2000yqm.googlegroups.com>
In reply to#3231
On May 4, 5:26 pm, Keith Thompson <ks...@mib.org> wrote:
> "Kleuskes & Moos" <kleu...@xs4all.nl> writes:
>
>
>
>
>
>
>
>
>
> > On May 3, 9:03 pm, Keith Thompson <ks...@mib.org> wrote:
> [...]
> >> Right.  The important distinction here is that the result of isalpha()
> >> is purely a yes/no result, *not* a success/failure result.  If isalpha()
> >> could tell you either
> >>     Yes, that's an alphabetic character
> >> or
> >>     No, that's not an alphabetic character
> >> or
> >>     Oops, I can't tell what that is
> >> the it would need a different interface.  In fact, none of the is*()
> >> functions have any way to indicate failure.
>
> > Perhaps that's got to do with the fact that they cannot actually fail.
> > Whatever the input, it's always possible to say wether it codes for an
> > letter, a number, upper or lower case character or not.
>
> Well, sort of.  The argument of the is*() function is an int,
> but its value is required to be representable as an unsigned char
> or to be equal to EOF.  The standard *could* have specified some
> kind of error handling for isalpha(UCHAR_MAX + 1), but instead it
> just says the behavior is undefined.  Similarly, the behavior of
> feof(FILE*(NULL)) is undefined.

Aye, it could have introduced a check, and it might have ordained
array-bounds-checking, too, but the fact of the matter is it doesn't.
and it seems aginst the spirit of C, too. Besides, returning false for
isalpha(65535) is a very reasonable implementation of that particular
bit of undefined behavior and I suspect most compilers will do.

> The choice was between imposing a small burden on the caller to
> avoid passing bad arguments, and making the interface substantially
> more inconvenient.

Yup. And the ghost of C demands it's the programmers responsibility.
Fortunately C is not Pascal.

> > However, for functions that might actually fail, the consideration is
> > actually an important one.
>
> Right.  If you want to have a function that returns a yes/no result,
> but the caller can't reliably avoid passing invalid arguments,
> you might have it return an error code (zero for success, non-zero
> for error) and pass the actual result via an int* argument.

Ack.

> (Languages with exception handling generally don't have this problem.)

:)

Instead they have other problems. The Law of Conservation of Misery is
unrelenting...

[toc] | [prev] | [next] | [standalone]


#3243

FromKeith Thompson <kst-u@mib.org>
Date2011-05-04 17:54 -0700
Message-ID<lnzkn2rmoz.fsf@nuthaus.mib.org>
In reply to#3240
"Kleuskes & Moos" <kleuske@xs4all.nl> writes:
> On May 4, 5:26 pm, Keith Thompson <ks...@mib.org> wrote:
[...]
>> Well, sort of.  The argument of the is*() function is an int,
>> but its value is required to be representable as an unsigned char
>> or to be equal to EOF.  The standard *could* have specified some
>> kind of error handling for isalpha(UCHAR_MAX + 1), but instead it
>> just says the behavior is undefined.  Similarly, the behavior of
>> feof(FILE*(NULL)) is undefined.
>
> Aye, it could have introduced a check, and it might have ordained
> array-bounds-checking, too, but the fact of the matter is it doesn't.
> and it seems aginst the spirit of C, too. Besides, returning false for
> isalpha(65535) is a very reasonable implementation of that particular
> bit of undefined behavior and I suspect most compilers will do.

In my experience, at least some implementations define macros for
the is*() functions, macros that work by indexing into arrays.
isalpha(65535) will go well outside the bounds of the array,
with unpredictable results.  (At least one implementation I've
seen defensively allows for small negative arguments, so (signed)
char arguments work as they should, even though the standard doesn't
require them to.  But you shouldn't depend on that.)

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#3319

From"Kleuskes & Moos" <kleuske@xs4all.nl>
Date2011-05-05 12:03 -0700
Message-ID<0f08f919-f319-4108-b5ee-e4f7889de06a@s2g2000yql.googlegroups.com>
In reply to#3243
On May 5, 2:54 am, Keith Thompson <ks...@mib.org> wrote:
> "Kleuskes & Moos" <kleu...@xs4all.nl> writes:
>
> > On May 4, 5:26 pm, Keith Thompson <ks...@mib.org> wrote:
> [...]
> >> Well, sort of.  The argument of the is*() function is an int,
> >> but its value is required to be representable as an unsigned char
> >> or to be equal to EOF.  The standard *could* have specified some
> >> kind of error handling for isalpha(UCHAR_MAX + 1), but instead it
> >> just says the behavior is undefined.  Similarly, the behavior of
> >> feof(FILE*(NULL)) is undefined.
>
> > Aye, it could have introduced a check, and it might have ordained
> > array-bounds-checking, too, but the fact of the matter is it doesn't.
> > and it seems aginst the spirit of C, too. Besides, returning false for
> > isalpha(65535) is a very reasonable implementation of that particular
> > bit of undefined behavior and I suspect most compilers will do.
>
> In my experience, at least some implementations define macros for
> the is*() functions, macros that work by indexing into arrays.
> isalpha(65535) will go well outside the bounds of the array,
> with unpredictable results.

True. That would be another acceptable implementation of undefined
behavior, not the most convenient one, but still.

>  (At least one implementation I've
> seen defensively allows for small negative arguments, so (signed)
> char arguments work as they should, even though the standard doesn't
> require them to.  But you shouldn't depend on that.)

Depending on undefined behavior is a no-no of epic proportions anyway,
however conveniently the actual implementation deals with it. But
that's kicking in an open door...

Tjuus,

Kleuske.

[toc] | [prev] | [next] | [standalone]


#3169

FromJames Dow Allen <jdallen2000@yahoo.com>
Date2011-05-03 03:45 -0700
Message-ID<296771a0-5798-4bcc-859a-7cd4d48a7c06@z7g2000prh.googlegroups.com>
In reply to#3162
As James Kuyper says, best is to have the return value
implicit in the function name:
   is_kosher(this.soup) && do_serve(&this);
or
   dad = find_father();
   if (dad == NULL) {
       /* process orphan */
   }

Letting zero represent incorrect/error is often good enough:
many simple programs will handle all error returns from a
simple function the same, so a single error "reason" is enough.

James

[toc] | [prev] | [next] | [standalone]


#3198

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-05-03 20:50 +0000
Message-ID<slrnis0ql4.gtj.grahn+nntp@frailea.sa.invalid>
In reply to#3169
On Tue, 2011-05-03, James Dow Allen wrote:
> As James Kuyper says, best is to have the return value
> implicit in the function name:
>    is_kosher(this.soup) && do_serve(&this);
> or
>    dad = find_father();
>    if (dad == NULL) {
>        /* process orphan */
>    }
>
> Letting zero represent incorrect/error is often good enough:
> many simple programs will handle all error returns from a
> simple function the same, so a single error "reason" is enough.

Yes. In my experience, lots of people want to be as generic as possible
and let pretty much *everything* have 0 for success and non-zero for
failure. This makes the calling code much harder to read.

It's worth /a lot/ to have calling code which reads naturally, like J.D.A.'s
examples above. Not like strcmp() or many POSIX functions.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .  .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#3171

Frompete <pfiland@mindspring.com>
Date2011-05-03 07:50 -0400
Message-ID<4DBFEBF4.5147@mindspring.com>
In reply to#3162
pozz wrote:
> 
> A very simple question. What do you use as the return value of a
> function for error/ok results?
> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> for errors.

When there may be several various error return codes,
then use 0 for success.

When there are *not* several various error return codes,
such as in the isspace function 
and the the other <ctype.h> functions,
then use 0 for failure.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#3187

FromKeith Thompson <kst-u@mib.org>
Date2011-05-03 12:04 -0700
Message-ID<ln62prvc50.fsf@nuthaus.mib.org>
In reply to#3171
pete <pfiland@mindspring.com> writes:
> pozz wrote:
>> A very simple question. What do you use as the return value of a
>> function for error/ok results?
>> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
>> for errors.
>
> When there may be several various error return codes,
> then use 0 for success.
>
> When there are *not* several various error return codes,
> such as in the isspace function 
> and the the other <ctype.h> functions,
> then use 0 for failure.

As I said in another followup, the is*() functions don't return
0 for *failure*.  A return value of 0 means that the function
successfully answered the question -- and the answer was no.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Nokia
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#3172

FromMartin Ambuhl <mambuhl@earthlink.net>
Date2011-05-03 07:59 -0400
Message-ID<7PydnbOre7mNcyLQnZ2dnUVZ_tSdnZ2d@earthlink.com>
In reply to#3162
On 5/3/2011 4:31 AM, pozz wrote:

> Another strategy is to define custom error code:
>
> #define ERROR_OK  0
> #define ERROR_UNDEFINED 1
> #define ERROR_WRONGVALUE 2

But not with those names.  These names are reserved for the implementation.

[toc] | [prev] | [next] | [standalone]


#3175

FromMark Storkamp <mstorkamp@yahoo.com>
Date2011-05-03 08:46 -0500
Message-ID<mstorkamp-AB5B3A.08455403052011@62-183-169-81.bb.dnainternet.fi>
In reply to#3162
In article <error-codes-20110503151314@ram.dialup.fu-berlin.de>,
 ram@zedat.fu-berlin.de (Stefan Ram) wrote:

> pozz <pozzugno@gmail.com> writes:
> >I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> >for errors.
> 
>   0 means »no error«, since there is only one way to
>   succeed, but many ways to fail.
> 
> >if (!myfuction()) printf("OK\n");
> 
>   Yes, the »!« looks ugly there, but often one wants to handle
>   the error in some way:

To steal a page from BCPL you can always do something like this:

#define unless(c) if(!(c))

Then you have

unless (myfunction()) printf("OK\n");

> 
> if( int const code = alpha() )error( code ); else printf ...
> 
>   (I know that one cannot define variables in the
>   if expression, but it would be nice.)

[toc] | [prev] | [next] | [standalone]


#3181

FromStephen Sprunk <stephen@sprunk.org>
Date2011-05-03 10:13 -0500
Message-ID<ipp639$des$1@dont-email.me>
In reply to#3162
On 03-May-11 03:31, pozz wrote:
> A very simple question. What do you use as the return value of a
> function for error/ok results?
> I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> for errors.

General rules:

1. If one success state and many error states, let 0 indicate success.

2. If one error state and many success states, let 0 indicate error.

3. If many success states and many error states, let negative indicate
error and non-negative indicate success.

> If !=0 is ok, I can write:
> 
>   if (myfunction()) printf("OK\n");
> 
> but I have only one error code (0), while, in some cases, it could be
> useful to have more informations about the type of error.

This is usually the case.

> If !=0 is error I can have several error codes, but I have to write
> 
>   if (!myfuction()) printf("OK\n");
> 
> that apparently seems myfunction has not terminated with success.

You could consider rewriting that line as:

if (myfuction()==0) printf("OK\n");

That form has the same meaning to the compiler, but some folks feel it
conveys a different/better meaning to humans.  This frequently comes up
in debates about strcmp() et al, for example.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#3195

FromWilliam Ahern <william@wilbur.25thandClement.com>
Date2011-05-03 13:08 -0700
Message-ID<ru3698-ldj.ln1@wilbur.25thandClement.com>
In reply to#3181
Stephen Sprunk <stephen@sprunk.org> wrote:
> On 03-May-11 03:31, pozz wrote:
> > A very simple question. What do you use as the return value of a
> > function for error/ok results?
> > I can't decide between 0 for error and !=0 for ok, or 0 for ok and !=0
> > for errors.

> General rules:

> 1. If one success state and many error states, let 0 indicate success.

> 2. If one error state and many success states, let 0 indicate error.

> 3. If many success states and many error states, let negative indicate
> error and non-negative indicate success.

This is the approach taken by snprintf(), and it's very annoying. On success
you end up with a value that really should be kept in a size_t, for
comparing with other similar values. Which means you inevitably end up
having to convert (or worry about missed implicit conversions) the value in
the common case. Then, to make matters worse, almost half the value space is
wasted for a simple -1. And to add insult to injury, although there can be
multiple error states, you still have to query a separate object. (So I
guess it sort of falls between #2 and #3.)

I would discard #3. If there are many error states, overload a single value
in the success space (an unlikely value, like 0, or more importantly a value
which if misused is unlikely to cause havoc, also typically 0), and take a
separate parameter analogous to errno. Otherwise, just return an errno-like
object.

I religiously follow #1 and #2. If #1, I return an (int). If #2 I take a
pointer to an (int). Positive values for the (int) object are reserved for
saving errno or reusing standard error macros. The standard says that errno
values most be positive, and if POSIX doesn't also guarantee this for
extensions it appears to be the universal behavior.

Negative values I reserve for application use, to be apportioned to each
library. To avoid clashes, present and future, I store in the upper bits a
likely unique identifer. For example, the error range for my DNS library
will start at -(('D' << 24) | ('N' << 16) | ('S' << 8)). (I realize (int) is
only guaranteed to be 16-bits, but the principle still applies, although
perhaps not as simple.)

I've toyed with the idea of overloading strerror(), but in general as long
as library dependencies are hierarchical and fairly shallow (as they almost
always are in practice), then simply passing an error value to the
_strerror() method of a library is sufficient, and each library can forward
negative errors as necessary, passing positive errors to strerror().

I use this method everywhere, often wrapping standard routines like malloc
and snprintf:

	void *make(size_t size, int *error);
	size_t fmtstr(void *dst, size_t lim, int *error, const char *fmt, ...);

It has worked extremely satisfactorily for a couple of years now. Since I
settled on this solution I haven't looked back. It has regularized by my
error handling habits, where how a particular routine returns an error is
not nearly as important as consistency and convenience across all the
routines.

[toc] | [prev] | [next] | [standalone]


#3185

FromKenneth Brody <kenbrody@spamcop.net>
Date2011-05-03 13:23 -0400
Message-ID<L6OdnYkzV8mMp13QnZ2dnUVZ_tidnZ2d@bestweb.net>
In reply to#3162
On 5/3/2011 4:31 AM, pozz wrote:
[...]
> #define ERROR_OK  0
> #define ERROR_UNDEFINED 1
> #define ERROR_WRONGVALUE 2
[...]

Nit:

Those are, technically, all reserved for implementation-defined error codes. 
  (7.26.2 reserves "macros that begin with E and a digit or E and an 
uppercase letter".)

-- 
Kenneth Brody

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web