传统的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宏,最终扩展为一个函数。考虑到将字符串解析为整数并不是一件繁重的工作,这似乎有点昂贵。
那么,在没有strtol
的情况下实现errno
更好,但使用其他一些方法来指示溢出是否更好呢?
喜欢:
long strtol(const char *nptr, char **endptr, int base, bool *is_overflow);
代替
long strtol(const char *nptr, char **endptr, int base);
答案 0 :(得分:4)
在没有errno的情况下实现strtol更好吗...
否。
...但是使用其他方法来指示溢出吗?
否。
long int strtol(const char * restrict nptr, char ** restrict endptr, int base);
strtol()
是标准的C库函数,任何实现都必须遵守3个输入的正确使用,并且必须遵守errno
。
当然,OP可以根据需要实现其他一些my_strtol()
。
关于避免errno
的任何性能问题都是微优化但也是合理的设计目标。
这实际上取决于如何将 string 问题传达给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);
答案 1 :(得分:0)
除了errno
中的strtol()
之外,实际上还有一些开销,例如跳过空格,照顾底数(10或六),检查字符...
在特定环境中,速度是至关重要的,并且您知道所提供的字符串是以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;
}
,然后选择内联。