Ama*_*rab 1 c c++ type-conversion strict-aliasing strlen
我发现这个 "快速strlen函数"实现:
// for x86 only
size_t my_strlen(const char *s) {
size_t len = 0;
for(;;) {
unsigned x = *(unsigned*)s;
if((x & 0xFF) == 0) return len;
if((x & 0xFF00) == 0) return len + 1;
if((x & 0xFF0000) == 0) return len + 2;
if((x & 0xFF000000) == 0) return len + 3;
s += 4, len += 4;
}
}
Run Code Online (Sandbox Code Playgroud)
这里使用的优化技术显然很简单:通过自然CPU字读取内存(代码是旧的并假定为x32 CPU),而不是简单的字节.
但是这段代码违反了别名规则,因此会导致未定义的行为,这些行为可以由编译器自由优化(那些使代码更快,但是更多).
我现在也看到它不可移植,因为它与little-endian endianness有关.
或者可能是我完全错了,上面的代码是正确的?这对C来说是否正确?对于C++?
这只是非常糟糕的代码.甚至代码的作者警告:
如果不可读的内存页面位于字符串结尾之后,此函数将崩溃.防止这种情况的最简单方法是在字符串末尾分配3个额外字节.
dword可以是未对齐的,但x86架构允许访问未对齐的数据.对于小字符串,对齐将比未对齐读取的惩罚花费更多时间.
代码不可移植:如果使用64位处理器,则必须添加另外4个条件.对于大端架构,条件的顺序应该颠倒过来.
即使这没有打破别名规则,编码人员负担my_strlen工作的负担也是完全没有道理的.已经多次说过,strlen这已经超出了普通编码器可以完成的任何事情.
但是应该为C++做一个额外的陈述:C++ 的创建者Bjarne Stroustrup,在他的书第4章的最后一页:"C++编程语言"中说:
喜欢
stringsC风格的字符串
你会发现它的大小string远远超过了找到C-String的大小.
编辑:
在你的评论中,你说你正在使用StaticallyBufferedString,它声称解决了string"池化内存模型",这导致:
我想建议C++ 17 string_view,它与所有C++ 17一样构建时考虑了多线程.它提供了string由堆和constexpr友好的C-Strings 支持的功能.您甚至可以通过以下方式快速了解它namespace experimental:http://en.cppreference.com/w/cpp/experimental/basic_string_view与您在StaticallyBufferedStrings上的时间不同,您获得的知识将非常便携并适用于任何未来你做的C++工作!