C標準ライブラリ Muslのatoi関数実装 では、符号付き整数オーバーフロー回避のため負数範囲で10進数値を減算してゆき最後に符号反転を行っている。
int atoi(const char *s) { int n=0, neg=0; while (isspace(*s)) s++; switch (*s) { case '-': neg=1; case '+': s++; } /* Compute n as a negative number to avoid overflow on INT_MIN */ while (isdigit(*s)) n = 10 * n - (*s++ - '0'); return neg ? n : -n; }
C言語の符号付き整数型(int
)では “2の補数” 表現が用いられるため*1、最大値INT_MAX
より最小値INT_MIN
の絶対値が 1 だけ大きくなり(例:16bit幅ならINT_MAX = 32767
, INT_MIN = -32768
)、正数範囲の累積計算では値-INT_MIN
を表現できず未定義動作(undefined behavior)を引き起こしてしまう。*2
その他のC標準ライブラリ実装(glibc, BSD libc, Newlib)では、単純にstrtol
関数へ実装移譲している。
int atoi (const char *s) { return (int) strtol (s, NULL, 10); }
ノート:int
型よりlong
型の値域が広い場合strtol
関数戻り値キャストで未定義動作(undefined behavior)となるが、そもそもC標準ライブラリatoi
関数仕様では「戻り値がint
型の値域外となる場合の動作は未定義(the behavior is undefined)」とされるため何ら問題はない。いいね?
- 2022-01-08追記:
long
→int
型変換において変換先の符号付き整数型で表現きない値の場合、処理系定義(implementation-defined)の値が得られるか処理系定義のシグナルが発生する(thanks to emkさんコメント)。
C99 3.4.3/p3, 7.20.1/p1, 7.20.1.4/p8より引用(下線部は強調)。
EXAMPLE An example of undefined behavior is the behavior on integer overflow.
The functions
atof
,atoi
,atol
, andatoll
need not affect the value of the integer expressionerrno
on an error. If the value of the result cannot be represented, the behavior is undefined.
The
strtol
,strtoll
,strtoul
, andstrtoull
functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values,LONG_MIN
,LONG_MAX
,LLONG_MIN
,LLONG_MAX
,ULONG_MAX
, orULLONG_MAX
is returned (according to the return type and sign of the value, if any), and the value of the macroERANGE
is stored inerrno
.
関連URL