由于linux内核中没有很多常用的函数/宏,所以不能使用任何直接函数从字符串缓冲区中获取整型值。
这是我已经使用了很长时间的代码,它可以用于所有* NIX风格(可能没有任何修改)。
这是代码的修改形式,我从开源项目中使用了很长时间(现在不记得名字)。
#define ISSPACE(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r')) #define ISASCII(c) (((c) & ~0x7f) == 0) #define ISUPPER(c) ((c) >= 'A' && (c) <= 'Z') #define ISLOWER(c) ((c) >= 'a' && (c) <= 'z') #define ISALPHA(c) (ISUPPER(c) || ISLOWER(c)) #define ISDIGIT(c) ((c) >= '0' && (c) <= '9') unsigned long mystr_toul ( char* nstr, char** endptr, int base) { #if !(defined(__KERNEL__)) return strtoul (nstr, endptr, base); /* user mode */ #else char* s = nstr; unsigned long acc; unsigned char c; unsigned long cutoff; int neg = 0, any, cutlim; do { c = *s++; } while (ISSPACE(c)); if (c == '-') { neg = 1; c = *s++; } else if (c == '+') c = *s++; if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; for (acc = 0, any = 0; ; c = *s++) { if (!ISASCII(c)) break; if (ISDIGIT(c)) c -= '0'; else if (ISALPHA(c)) c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = INT_MAX; } else if (neg) acc = -acc; if (endptr != 0) *((const char **)endptr) = any ? s - 1 : nstr; return (acc); #endif }