2017-12-23 18 views
1

、それらが単純な整数の比較と一度に比較することができ、switch文で使用されるので、依然としてヒトのビットを維持しながら、符号なし32ビット整数にパック短い文字列/チャーアレイは、かなり有用です可読性。短い文字列を32ビット整数に変換する最も効率的な方法は何ですか?多くの目的のために

32ビット整数にこれらの短い文字列を変換するための最も一般的な方法は、シフトすることである/または:長すぎる

#include <stdint.h> 

uint32_t quadchar(const char* _str) 
{ 

    uint32_t result = 0; 

    for(size_t i=0; i<4; i++) 
    { 
     if(_str[i] == 0) 
      return result; 
     result = (result << 8) | _str[i]; 
    } 

    return result; 
} 

文字列は、切り捨てられます。

これまでのところは良いが、これは少し時間がかかりランタイム上で行う必要があります。 コンパイル時にもこれを実行できますか? C++ 11のよう

+2

。すでにC++ 11でこれを行う(再帰的に)方法を示す答えがあります。 C++ 03の場合、良い構文を得ることは事実上不可能ですが、C++ 03のソリューションの1つは、いくつかのスクリプトを使ったソースコードの前処理です。 –

+0

ユニオンメソッドは未定義の動作であり、その結果はCPUのエンディアンに依存します。 – Barmar

+0

@Barmar:true、thx。私はこの通路を削除しました。 – user2328447

答えて

0

、それはconstexpr specifierを使用して、実行時にゼロコストでコンパイル時にこれを実行することが可能です。

namespace Internal 
{ 
    uint32_t inline constexpr quadchar(char const *_input, 
     uint8_t _idx, uint32_t _result) 
    { 
     return _idx == 4 ? _result 
      : *_input ? quadchar (_input+1, _idx + 1, (_result << 8) | *_input) 
       : _result; 
    } 
} 

uint32_t inline constexpr quadchar(char const *_input) { 
    return Internal::quadchar(_input, 0, 0); 
} 

実装オーバーロードを内部名前空間に配置して、ユーザーから非表示にしました。上記のランタイムの例のように、構文はにifを使用することはできません。しかし、それは価値があると思います。

+0

この回答には、質問に適用された同じ移植性の警告が適用されます。変換された文字列が永続化されない、またはネットワークを介して送信されない場合は、問題ではない可能性があります。ここで 'honl()'の呼び出しが賢明かもしれません。多くのCPUでは、ごくわずかな命令にコンパイルされます。 – marko

+2

申し訳ありませんが、私はあなたが意味するものを正確に理解していません。ここで移植できないものは何ですか?私が見る限り、すべては移植可能で、非エンディアンに依存していなければなりません。 'honl()'は何ですか?それについて何も見つかりませんでした。 – user2328447

1

詳細ヘルパー機能の必要はありません:あなたは、デフォルト値を使用することができます。

とダブル三項演算子のための必要はありません:あなたは、単一のテスト

std::uint32_t inline constexpr quadchar (char const * input, 
             std::size_t idx = 0U, 
             std::uint32_t result = 0U) 
{ 
    return (idx < 4U) && *input 
     ? quadchar(input+1, idx+1U, (result << 8) | *input) 
     : result; 
} 

ですべてを行うことができます。しかし、それはもう少しポータブルで汎用的にするために、私は)

1示唆します「を含むことを覚えている(resultシフトをCHAR_BIT代わりに8を使用)idx限界

2ためsizeof()代わりに4を使用あなたはresultタイプのテンプレートタイプ(デフォルトではstd::uint32_t)を使用してください。あなたが他の返却のタイプのstd::uint32_t、または(たとえば別)

constexpr auto u64 = ichar<std::uint64_t>(ptr); 

をしたいときに

constexpr auto u32 = ichar(ptr); 

を呼び出すことができます

template <typename I = std::uint32_t> 
constexpr inline I ichar (char const * input, 
          I result = 0U, 
          std::size_t idx = 0U) 
{ 
    return (idx < sizeof(I)) && *input 
     ? ichar(input+1, idx+1U, (result << CHAR_BIT) | *input) 
     : result; 
} 

よう

何か。あなたは自分の関数に `constexpr`を追加する必要がC++ 14以降で

+0

ありがとうございます。 'sizeof()'とテンプレートのアイデアはとても良いです。 'CHAR_BIT'についてはあまりよく分かりません。 'CHAR_BIT'!= 8の場合、異なるシフトのため8ビットのcharの結果と異なる結果になります。私はこれがより多くの代わりに移植性が低いと思う。代わりに、入力文字で代わりに '&0xff'を追加するほうがよいでしょう。ヘルパー関数は、 'result'と' input'パラメータを隠すために実装されました。なぜなら、それらがユーザにとって意味をなさないからです。もちろん、デフォルトのパラメータもOKです。 – user2328447

+0

@ user2328447 - 'CHAR_BIT = 12 'のプラットフォームでは' std :: uint32_t'が存在するのですが) 'CHAR_BIT'について疑問を抱いていますが、' CHAR_BIT> 8 '(' 8 'が最小値です)、' input'のすべての文字は 'CHAR_BIT'ビットです。だから '(結果<< 8)| * input'あなたは前のcharの最後のビットと '* input'の最初のビットの衝突(またはビット)があります。 – max66

+0

@ user2328447 - そしてyes: '&0xff'のアイデアは良い代替解決策になるかもしれません。 (CHAR_BITS> 8の場合)いくつかのビットの使用を緩め、 'input'文字の右のビットを管理することは困難でプラットフォームに依存する可能性があるということを数えます。 – max66

関連する問題