2017-05-05 6 views
0

をuint8_tするため、バイト反転uint64_tを私はバイト順(convert big endian to little endian in C [without using provided func])を逆にする方法を知っている - この場合、私はまた、char型の配列に64ビットのUINTをコピーする方法を知っている__builtin_bswap64コピー配列

を使用したいです理想的にはmemcopy。 (How do I convert a 64bit integer to a char array and back?

私の問題は、これらの両方の組み合わせです。問題の根底には、私はこのコードを速く代替見つけようとしている:(?またはそれがない)memcopyをソース引数として__builtin_bswap64の結果を負いませんので

carr[33] = ((some64bitvalue >> 56) & 0xFF) ; 
carr[34] = ((some64bitvalue >> 48) & 0xFF) ; 
carr[35] = ((some64bitvalue >> 40) & 0xFF) ; 
carr[36] = ((some64bitvalue >> 32) & 0xFF) ; 
carr[37] = ((some64bitvalue >> 24) & 0xFF) ; 
carr[38] = ((some64bitvalue >> 16) & 0xFF) ; 
carr[39] = ((some64bitvalue >> 8) & 0xFF) ; 
carr[40] = (some64bitvalue & 0XFF); 

を、私はこれを試してみました:

*(uint64_t *)upub+33 = __builtin_bswap64(some64bitvalue); 

が、私は エラーで終わる:割り当て

の左オペランドとして必要な左辺値は、私はすべてで置き換えるしようとしている元のコードの高速化の代替はありますか?

+0

'upub'の種類は何ですか?おそらく厳密なエイリアシング規則に違反している可能性があります。 – user694733

+0

なぜあなたはそれが遅すぎると思いますか?アセンブリコードを見ましたか?プロフィールはありましたか?ポータブルで読みやすいコードを書くことに集中し(例えば、関数内でこれをラップするなど)、スピードの問題がある場合にのみ最適化します。 – Olaf

+0

私はスピードの問題があり、私は "時期尚早の最適化の問題"を認識しています。ここでは適用されません。私の仮定は純粋に直観に基づいていましたが、 '*((uint64_t *)upub + 33)= __builtin_bswap64(some64bitval);に対してベンチマークしました;私の直感は正しいことが分かりました。 – Perlator

答えて

3

これ:

*(uint64_t *)upub+33 = __builtin_bswap64(PplusQ[di][3]); 

そう左側がuint64_t、ない左辺値である

(*(uint64_t *) upub) + 33 = __builtin_bswap64(PplusQ[di][3]); 

として解析します。

これはどうでしょうか?

*(uint64_t *) (upub+33) = __builtin_bswap64(PplusQ[di][3]); 

か、アコンカグアのコメントとして、uint64_t *最初にupubをキャストすることを意味しましたか?

*((uint64_t *) upub + 33) = __builtin_bswap64(PplusQ[di][3]); 

upubのタイプは表示されませんでしたので、わかりません。また

、私はあなたが組合を通じて割り当てをGCCの-fno-strict-aliasingのようなものを使用するか、したいことがありので、本来は別のタイプを指しているaliasing rulesupub場合に問題があるかもしれないことを感じ、または1バイトでを持っています最初のコードスニペットと同じ時間です。

+0

'upub'とは何ですか?どのように宣言/設定されているかに応じて、UBを呼び出すことができます。 – Olaf

+0

@Olaf、私たちは分かりませんが、質問には言いません。私は情報が欠落していると言いましたが、エイリアスの可能性についても言及しました。私は、被験者の検証を一方的に見てうれしく思います。 – ilkkachu

+0

upub/carrは**です。**は 'uchar' /' uint8_t'の配列です。 '*(uint64_t *)(upub + 33)= __builtin_bswap64(PplusQ [di] [3]);は、すべての警告、pedanticやその他のホイッスルを有効にしています。また、元のコードよりも高速です。 – Perlator

1

としてあなたがコピーすることができます:upubを想定し

uint64_t tmp = __builtin_bswap64(some64bitvalue); 
memcpy(upub+33,&tmp,sizeof(tmp)); 

は、ポインタ変数

+0

動作しますが、元のコードよりも遅いです。 – Perlator

1

ビットシフトへの代替がないエンディアンに依存しないコードを書くことです。あなたのコードは既に理想に近いでしょう。

あなたが周りに遊ぶことができるのは、ハードコードされた数字の代わりにループを使用することです。

for(uint_fast8_t i=0; i<8; i++) 
{ 
    carr[i+offset] = (some64bitvalue >> (56-(i*8)) & 0xFF; 
} 

これは、システムによっては、これより遅くなったり、速くなったり、同等になることがあります。全体として、特定のシステムを念頭に置いてこのような手動最適化について議論するのは意味がありません。