glibc中strtoul的实现是否与C11标准冲突?
Does the implementation of strtoul in glibc conflicts with the C11 standard?
以下是glibc实现的stdlib.h
中函数strtoul
的说明:
Function: unsigned long int strtoul (const char *retrict string, char **restrict tailptr, int base)
Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.
The strtoul (“string-to-unsigned-long”) function is like strtol except it converts to an unsigned long int value. The syntax is the same as described above for strtol. The value returned on overflow is ULONG_MAX (see Range of Type).
If string depicts a negative number, strtoul acts the same as strtol but casts the result to an unsigned integer. That means for example that strtoul on "-1" returns ULONG_MAX and an input more negative than LONG_MIN returns (ULONG_MAX + 1) / 2.
strtoul sets errno to EINVAL if base is out of range, or ERANGE on overflow.
意思是,比如"-2"
会被转换成ULONG_MAX - 1
。但是 C11 标准 [7.22.1.4-8] 说:
The strtol, strtoll, strtoul, and strtoull 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, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.
所以按照标准,比如"-2"
应该转换成ULONG_MAX
。有冲突吗?
这可能是 glibc
在标准化之前实施功能的另一个案例。
是的,它有冲突。
不过,我认为 glibc 的结果更有用。如果你需要完美的合规性,你可以包装函数来执行转换。
没有冲突。
If the subject sequence begins with a minus sign, the value resulting from
the conversion is negated (in the return type). C11dr §7.22.1.4 5
unsigned
否定定义明确。
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type. §6.2.5 9
按照标准,“-2”应转换为ULONG_MAX - 2
。
所以可能 "Function: unsigned long ... overflow" 文本在某种程度上与 C 规范冲突(特别是 "input more negative than LONG_MIN
returns (ULONG_MAX + 1) / 2
)",但 strtoul()
功能是正确的。
以下是glibc实现的stdlib.h
中函数strtoul
的说明:
Function: unsigned long int strtoul (const char *retrict string, char **restrict tailptr, int base) Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.
The strtoul (“string-to-unsigned-long”) function is like strtol except it converts to an unsigned long int value. The syntax is the same as described above for strtol. The value returned on overflow is ULONG_MAX (see Range of Type).
If string depicts a negative number, strtoul acts the same as strtol but casts the result to an unsigned integer. That means for example that strtoul on "-1" returns ULONG_MAX and an input more negative than LONG_MIN returns (ULONG_MAX + 1) / 2.
strtoul sets errno to EINVAL if base is out of range, or ERANGE on overflow.
意思是,比如"-2"
会被转换成ULONG_MAX - 1
。但是 C11 标准 [7.22.1.4-8] 说:
The strtol, strtoll, strtoul, and strtoull 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, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.
所以按照标准,比如"-2"
应该转换成ULONG_MAX
。有冲突吗?
这可能是 glibc
在标准化之前实施功能的另一个案例。
是的,它有冲突。
不过,我认为 glibc 的结果更有用。如果你需要完美的合规性,你可以包装函数来执行转换。
没有冲突。
If the subject sequence begins with a minus sign, the value resulting from the conversion is negated (in the return type). C11dr §7.22.1.4 5
unsigned
否定定义明确。
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type. §6.2.5 9
按照标准,“-2”应转换为ULONG_MAX - 2
。
所以可能 "Function: unsigned long ... overflow" 文本在某种程度上与 C 规范冲突(特别是 "input more negative than LONG_MIN
returns (ULONG_MAX + 1) / 2
)",但 strtoul()
功能是正确的。