weiweishuo
weiweishuo

Reputation: 927

Is it better to implement strtol() without errno?

Traditional strtol() is usually used like this:

int main()
{
    errno = 0;
    char *s = "12345678912345678900";
    char *endptr;
    long i = strtol(s,  &endptr, 10);
    if(i == LONG_MAX && errno == ERANGE) 
        printf("overflow");
}

We need to access errno two times, and errno nowadays is usually a C macro finally expanded to a function. It seems a little expensive considering parsing string to integer isn't a heavy job.

So, is it better to implement strtol without errno but using some other ways to indicating overflow?

like:

long strtol(const char *nptr, char **endptr, int base, bool *is_overflow);

instead of

long strtol(const char *nptr, char **endptr, int base);

Upvotes: 2

Views: 754

Answers (2)

Déjà vu
Déjà vu

Reputation: 28830

There is actually some overhead besides errno in strtol(), like skipping spaces, taking care of the base (10 or hexa), check characters ...

In a specific environment where speed is critical and you know the string provided is a number base 10 that fits in a long, you could make your own quick function, like

#include <ctype.h>

long mystrtol(char *s) {
   long res = 0, minus = *s == '-';
   if (minus || *s == '+') s++;

   while (isdigit(*s)) {
      res = res*10 + (*s++ - '0');
   }

   return minus ? -res : res;
}

and choose to inline it.

Upvotes: 0

chux
chux

Reputation: 153338

is it better to implement strtol without errno ...

No.

... but using some other ways to indicating overflow?

No.

long int strtol(const char * restrict nptr, char ** restrict endptr, int base);

strtol() is a standard C library function and any implementation must adhere to proper use of the 3 inputs and errno to be compliant.


Of course OP can implement some other my_strtol() as desired.

Any performance concerns around avoiding errno are a micro-optimization yet a reasonable design goal.

It really comes down to how to conveys problems of string to long

  • Overflow "12345678912345678901234567890"

  • No conversions "abc"

  • Excess junk "123 abc"

  • Leading space allowed, trailing space allowed?

  • Allow various bases?

Once functionality about all exceptional cases are defined, not just overflow, then coding concerns about errno is useful, even if unlikely to make any meaningful performance improvements.

IMO, coding to one base only is likely a more productive path to speed improvements than errno.


OP code is not a robust strtol() usage. Suggest:

char *s = "12345678912345678900";

char *endptr;
errno = 0;
long i = strtol(s,  &endptr, 10);
if (errno == ERANGE) printf("Overflow %ld\n", i);
else if (s == endptr) printf("No conversion %ld\n", i);
else if (*endptr) printf("Extra Junk %ld\n", i);
else printf("Success %ld\n", i);

Upvotes: 4

Related Questions