strtoull関数はunsigned long long型を返す関数ですが、strtoul関数とほとんど内容は同じですので、具体的な解説は割愛します。strtoul関数の実装のうち、unsigned longの部分をunsigned long longに、ULONG_MAXの部分をULLONG_MAXに読み替えれば、strtoull関数になると思います。
int _space_sign(const char *s, const char **endptr);
unsigned long strtoul(const char * __restrict__ s, char ** __restrict__ endptr, int radix) { unsigned long result;
if (_space_sign(s, (const char**)&s) != 0) --s; // '-'の位置まで戻す
if (s[0] == '0') { ++s; if ((s[1] | 0x20) == 'x') { if (radix == 0 || radix == 16) { ++s; radix = 16; } } else if (radix == 0) radix = 8; } else if (radix == 0) radix = 10;
int c; for (result = 0; c = tolower((unsigned char)*s), isdigit(c) || ('a' <= c && c <= 'z'); s++) { int d = isdigit(c) ? c - '0' : c - 'a' + 10; if (d >= radix) break; if (result > (ULONG_MAX - d) / radix) { errno = ERANGE; result = ULONG_MAX; } else { result = result * radix + d; } }
この部分の解釈は難しいですね。 何度か規格を読み直したのですが、'-'を受け取った場合、errnoをERANGEに設定してULONG_MAXまたはULLONG_MAXを返すべきなのか、何事もなかったかのようにunsigned longまたはunsigned long longにキャストすればよいのかよくわかりませんでした。
規格では、「変換の結果の値は(返却値の型で)負数化したものとする」とありますが、「負数化」の定義がないので何ともいえません。 「新ANSI C言語辞典」でstrtoulのところを見ると、'-'は認識不能文字だとされているので、それを信じたのですが、既存の処理系を見ると、どれも'-'をそのまま受け取って、最後にunsigned longやunsigned long longでキャストしているようですね。