为什么使用“strlen30()”而不是“strlen()”?
我读过并想知道 sqlite 的源代码
static int strlen30(const char *z){
const char *z2 = z;
while( *z2 ){ z2++; }
return 0x3fffffff & (int)(z2 - z);
}
为什么使用 strlen30()
而不是 strlen()
(在 string.h 中)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
提交消息此更改指出:
The commit message that went in with this change states:
(这是我的答案 为什么将 strlen 重新实现为循环+减法?< /a> ,但它已关闭)
我无法告诉你他们必须重新实现它的原因以及他们选择的原因
int
而不是size_t
作为返回类型。但关于功能:标准参考
标准在(ISO/IEC 14882:2003(E))3.9.1 基本类型,4.中说:
标准的该部分没有定义有符号整数的溢出行为。如果我们看5。表达式,5.:
到目前为止已经溢出了。
至于两个指向数组元素的指针相减,5.7 加法运算符,6.:
看看18.1:
那么让我们看一下 C 标准(不过,我只有 C99 的副本),7.17 通用定义 :
对于
ptrdiff_t
不作进一步保证。然后,附件 E(仍在 ISO/IEC 9899:TC2 中)给出了有符号 long int 的最小量值,但不是最大值:现在
int
的最大值是多少,sqlite - strlen30()
的返回类型?让我们再次跳过将我们引向 C 标准的 C++ 引用,我们将在 C99 附录 E 中看到int
的最小最大值:摘要
signed long
,且不小于 32 位。int
被定义为至少 16 位长。int
的结果。strlen30
确实对指针减法结果应用按位或:通过将指针减法结果截断为最大值 3FFFFFFF16 = 1073741823< 来防止未定义行为子>10。
我不确定他们为什么选择这个值,因为在大多数机器上,只有 最有效位表示符号。与标准相比,选择最小值 INT_MAX 可能是有意义的,但在不知道更多细节的情况下,1073741823 确实有点奇怪(尽管它当然完美地实现了其函数上面的注释:截断为 30 位和防止溢出)。
(this is my answer from Why reimplement strlen as loop+subtraction? , but it was closed)
I can't tell you the reason why they had to re-implement it, and why they chose
int
instead ifsize_t
as the return type. But about the function:Standard References
The standard says in (ISO/IEC 14882:2003(E)) 3.9.1 Fundamental Types, 4.:
That part of the standard does not define overflow-behaviour for signed integers. If we look at 5. Expressions, 5.:
So far for overflow.
As for subtracting two pointers to array elements, 5.7 Additive operators, 6.:
Looking at 18.1:
So let's look at the C standard (I only have a copy of C99, though), 7.17 Common Definitions :
No further guarantee made about
ptrdiff_t
. Then, Annex E (still in ISO/IEC 9899:TC2) gives the minimum magnitude for signed long int, but not a maximum:Now what are the maxima for
int
, the return type forsqlite - strlen30()
? Let's skip the C++ quotation that forwards us to the C-standard once again, and we'll see in C99, Annex E, the minimum maximum forint
:Summary
ptrdiff_t
is not bigger thansigned long
, which is not smaller than 32bits.int
is just defined to be at least 16bits long.int
of your platform.strlen30
does applies a bitwise or upon the pointer-subtract-result:That prevents undefiend behaviour by truncation of the pointer-subtraction result to a maximum value of 3FFFFFFF16 = 107374182310.
I am not sure about why they chose exactly that value, because on most machines, only the most significant bit tells the signedness. It could have made sense versus the standard to choose the minimum
INT_MAX
, but 1073741823 is indeed slightly strange without knowing more details (though it of course perfectly does what the comment above their function says: truncate to 30bits and prevent overflow).CVS 提交消息显示:
我找不到任何对此提交的进一步参考或解释他们如何在该地方发生溢出。我相信这是某些静态代码分析工具报告的错误。
The CVS commit message says:
I couldn't find any further reference to this commit or explanation how they got an overflow in that place. I believe that it was an error reported by some static code analysis tool.