首页 文章

没有errno实现strtol()更好吗?

提问于
浏览
1

传统 strtol() 通常使用如下:

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

我们需要两次访问 errno ,而 errno 现在通常是一个C宏,最终扩展为一个函数 . 考虑将字符串解析为整数并不是一项繁重的工作,这似乎有点贵 .

那么,没有 errno 实现 strtol 更好,但是使用其他一些方法来指示溢出?

喜欢:

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

代替

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

2 回答

  • 0

    没有errno实现strtol更好吗?

    没有 .

    ...但是使用其他一些方法来指示溢出?

    没有 .

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

    strtol() 是标准C库函数,任何实现都必须遵守正确使用3个输入和 errno 才能兼容 .


    当然OP可以根据需要实现其他一些 my_strtol() .

    避免 errno 的任何性能问题都是微观优化,但却是一个合理的设计目标 .

    它真的归结为如何将字符串的问题传达给 long

    • 溢出 "12345678912345678901234567890"

    • 无转化 "abc"

    • 多余的垃圾 "123 abc"

    • 允许领先的空间,允许尾随空间?

    • 允许各种基地?

    一旦定义了关于所有异常情况的功能,而不仅仅是溢出,那么关于 errno 的编码问题是有用的,即使不太可能进行任何有意义的性能改进 .

    IMO,只编码到一个基地可能是一个比 errno 更有效的速度改进途径 .


    OP代码不是一个强大的 strtol() 用法 . 建议:

    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);
    
  • 4

    strtol() 中除了 errno 之外实际上有一些开销,比如跳过空格,照顾基数(10或hexa),检查字符......

    specific environment 中,速度至关重要且 you know the string provided is a number base 10 适合 long ,您可以自己创建快速功能,例如

    #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;
    }
    

    并选择内联它 .

相关问题