快速strlen功能vs别名规则

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++?

Jon*_*Mee 5

这只是非常糟糕的代码.甚至代码的作者警告:

  • 如果不可读的内存页面位于字符串结尾之后,此函数将崩溃.防止这种情况的最简单方法是在字符串末尾分配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++工作!