3

我有很多字符串,每个字符串的大小为 8 或更小。

我需要在那里使用memcmp()/进行大量比较strcmp()

我想知道如果我将它们全部转换为std::uint64_t. 在这种情况下,至少理论上比较将是无分支的,也将发生在单 CPU 操作中。

有没有人尝试过类似的东西?

这是一些生成这些数字的测试代码。我假设小端机器。

htobe32()我知道如果我使用/可以显着简化代码htobe64()

#include <cstdint>

#include <algorithm>    // std::reverse_copy

namespace rev_impl{
    template<typename T>
    T rev(const char *s){
        T t;
        char *pt = reinterpret_cast<char *>(&t);

        std::reverse_copy(s, s + sizeof(T), pt);

        return t;
    }
}

inline uint32_t rev32(const char *s){
    return rev_impl::rev<uint32_t>(s);
}

inline uint64_t rev64(const char *s){
    return rev_impl::rev<uint64_t>(s);
}


#include <iostream>
#include <iomanip>

template<typename T>
void print_rev(const char *s){
    constexpr auto w = sizeof(T) * 2;

    std::cout << std::setw(w) << std::setfill('.') << std::hex << rev_impl::rev<T>(s) << '\n';
}

inline void print_rev32(const char *s){
    return print_rev<uint32_t>(s);
}

inline void print_rev64(const char *s){
    return print_rev<uint64_t>(s);
}

int main(){
    print_rev64("\0\0\0\0\0\0\0a");
    print_rev64("a\0\0\0\0\0\0\0");

    print_rev32("Niki");
    print_rev32("Nika");
    print_rev32("Nikz");
}

这是测试输出:

..............61
6100000000000000
4e696b69
4e696b61
4e696b7a
4

1 回答 1

0

如果您必须只转换字符串文字,您可以编写rev接受chars 数组,如下所示

template <typename T, std::size_t N,
          typename = typename std::enable_if<(N<=sizeof(T)+1U)>::type>
constexpr T rev (char const (&arr)[N])
 {
   T ret = 0;

   std::size_t  ui = -1;

   while ( ++ui < N-1U )
      ret <<= CHAR_BIT, ret |= arr[ui];

   while ( ++ui < sizeof(T) )
      ret <<= CHAR_BIT;

   return ret;
 }

请注意,从 C++14 开始,可以定义此函数constexpr,因此您可以编写如下内容

constexpr auto fb = rev<std::uint64_t>("foobar");

以下是您重写的代码以使用字符串文字

#include <cstdint>
#include <climits>
#include <iostream>
#include <iomanip>
#include <type_traits>

namespace rev_impl
 {
    template <typename T, std::size_t N,
              typename = typename std::enable_if<(N<=sizeof(T)+1U)>::type>
    T rev (char const (&arr)[N])
     {
       T ret = 0;

       std::size_t  ui = -1;

       while ( ++ui < N-1U )
          ret <<= CHAR_BIT, ret |= arr[ui];

       while ( ++ui < sizeof(T) )
          ret <<= CHAR_BIT;

       return ret;
     }
 }

template <typename T, std::size_t N>
inline uint32_t rev32 (char const (&s)[N])
 { return rev_impl::rev<uint32_t>(s); }

template <typename T, std::size_t N>
inline uint64_t rev64 (char const (&s)[N])
 { return rev_impl::rev<uint64_t>(s); }

template<typename T, std::size_t N>
void print_rev (char const (&s)[N])
 {
   constexpr auto w = sizeof(T) * 2;

   std::cout << std::setw(w) << std::setfill('.') << std::hex
      << rev_impl::rev<T>(s) << '\n';
 }

template <std::size_t N>
inline void print_rev32 (char const (&s)[N])
 { return print_rev<uint32_t>(s); }

template <std::size_t N>
inline void print_rev64 (char const (&s)[N])
 { return print_rev<uint64_t>(s); }

int main ()
 {
   print_rev64("\0\0\0\0\0\0\0a");
   print_rev64("a\0\0\0\0\0\0\0");

   print_rev32("Niki");
   print_rev32("Nika");
   print_rev32("Nikz");
 }
于 2018-02-18T15:13:28.050 回答