glibc中strtoul的实现是不是与C11标准冲突?

Posted

技术标签:

【中文标题】glibc中strtoul的实现是不是与C11标准冲突?【英文标题】:Does the implementation of strtoul in glibc conflicts with the C11 standard?glibc中strtoul的实现是否与C11标准冲突? 【发布时间】:2015-12-29 23:54:18 【问题描述】:

以下是glibc实现的stdlib.h中函数strtoul的描述:

功能:unsigned long int strtoul (const char *retrict string, char **restrict tailptr, int base) 初步:| MT-安全语言环境 | AS-安全 |交流安全 |请参阅 POSIX 安全概念。

strtoul(“string-to-unsigned-long”)函数与 strtol 类似,只是它转换为 unsigned long int 值。语法与上面描述的 strtol 相同。溢出时返回的值为 ULONG_MAX(请参阅类型范围)。

如果字符串表示负数,strtoul 的作用与 strtol 相同,但会将结果转换为无符号整数。这意味着例如 strtoul on "-1" 返回 ULONG_MAX 并且比 LONG_MIN 更负的输入返回 (ULONG_MAX + 1) / 2。

如果基数超出范围,strtoul 将 errno 设置为 EINVAL,或者在溢出时设置 ERANGE。

这意味着,例如,"-2" 将被转换为ULONG_MAX - 1。但是 C11 标准 [7.22.1.4-8] 说:

strtol、strtoll、strtoul 和 strtoull 函数返回转换后的 价值,如果有的话。如果无法执行转换,则返回零。 如果正确值超出可表示值的范围,则返回 LONG_MIN、LONG_MAX、LLONG_MIN、LLONG_MAX、ULONG_MAX 或 ULLONG_MAX(根据返回类型和值的符号,如果有),并且宏ERANGE的值存储在errno中。

因此按照标准,例如"-2" 应转换为ULONG_MAX。是不是有冲突?

【问题讨论】:

请注意,glibc 比 C 标准更遵循posix。然而,C11 7.22.1.4.5 似乎也处理了 - 符号,但我很不清楚是否应该在你引用的 7.22.1.4-8 部分发生之前进行否定。 @nos,谢谢,但是正如我回复chux的,即使发生在溢出转换之后,仍然存在冲突。 【参考方案1】:

没有冲突。

如果主题序列以减号开头,则产生的值来自 转换被否定(在返回类型中)。 C11dr §7.22.1.4 5

unsigned 否定定义明确。

涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果会以比结果类型可以表示的最大值大一的数字为模减少。 §6.2.5 9

按照标准,“-2”应转换为ULONG_MAX - 2

因此,也许“函数:无符号长 ...

【讨论】:

谢谢。正如@nos 所说,我不知道否定是在我引用的溢出转换之前还是之后发生的。但是即使它发生在您所说的溢出转换之后,输入比 LONG_MIN 更负可能仍然存在冲突,例如 - ULONG_MAX(实现将返回 (ULONG_MAX + 1) / 2 而它应该是1 按标准)。 @Shenke 我刚刚在 32 位和 64 位主机上测试过,它返回 1。 @nos 我很困惑。看起来 glibc 的真正实现与它所记录的并不完全相同。文件是否太旧?我在这个网站上找到它:gnu.org/software/libc/manual/html_mono/libc.html @Shenke 根据 C 规范 7.22.1.4-8,轻轻暗示(注意函数名称和范围限制的顺序)strtoul(),使用范围 [0...ULONG_MAX],而不是 [LONG_MIN ...ULONG_MAX]。根据 C11dr §7.22.1.4 5,否定发生在“转换产生的值”之后。【参考方案2】:

这可能是glibc 在标准化发生之前实现功能的另一种情况。

是的,它有冲突。

不过,我认为 glibc 的结果更有用。如果您需要完美的合规性,您可以包装函数来执行转换。

【讨论】:

谢谢。我同意你的看法。你知道在哪里报告这个错误吗? @Shenke:视情况而定。如果错误在标准中,则不清楚在哪里报告。如果您认为 glibc 有错误,那么需要有一些说服力来用新标准替换他们的标准。变化可能会扰乱许多现有用途。 -2 示例中没有冲突,glibc 正确遵循标准。 (这个问题误解了标准)。比LONG_MIN 更负的值将是另一种情况,尽管在做出判断之前最好测试 glibc 函数的实际行为而不是相信发布的文档(这没什么意义)

以上是关于glibc中strtoul的实现是不是与C11标准冲突?的主要内容,如果未能解决你的问题,请参考以下文章

glibc 附带的 C 是不是有自动调整大小的数组/动态数组实现?

16进制转10进制,是否要用strtoul函数

对于二维矩阵,它在 C++11 中是不是与 C11 中的函数相似?

C11简洁之道:类型推导

GNU C编译器的gnu11和c11

第一章 C语言编程