2017-05-05 36 views
0

我知道如何扭转字节顺序(convert big endian to little endian in C [without using provided func]) - 在这种情况下,我想使用__builtin_bswap64复制字节反转uint64_t中以uint8_t数组

我也知道如何将一个64位UINT复制到一个字符数组 - 理想的记忆体。 (How do I convert a 64bit integer to a char array and back?

我的问题是这两种的结合。在问题的根源,我试图找到这段代码更快的替代方案:

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); 

由于存储器复制不采取__builtin_bswap64源论证的结果(?或者它),我想这:

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

,但我最终的 错误:左值要求作为分配的左操作数

是否有快速替代原来的代码我想在所有的更换?

+0

什么的'upub'类型?您可能违反了严格的别名规则。 – user694733

+0

为什么你认为它太慢?你有没有看看汇编代码?你有个人资料吗?首先集中编写便携和可读代码(例如,通过将其封装在一个函数中),只有在遇到速度问题时才进行优化。 – Olaf

+0

我确实有速度问题,我知道“过早优化问题”。这里不适用。我的假设完全基于直觉,但基于'*((uint64_t *)upub + 33)= __builtin_bswap64(大约64bitval);'我的直觉证明是正确的。 – Perlator

回答

3

此:

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

解析作为

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

所以左手侧是uint64_t,不是左值。

所以将这项工作?

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

还是你的意思是投upubuint64_t *第一,因为阿空加瓜评论?

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

我没有看到提到的upub的类型,所以我不能说。

另外,我有一种感觉,有可能是与aliasing rules如果upub原本指向另一种类型的问题,所以你可能想通过工会使用类似gcc的-fno-strict-aliasing或进行分配,或者在一个字节就像你的第一个代码片段一样。

+0

什么是'upub'?取决于如何声明/设置,这可以并将调用UB。 – Olaf

+0

@Olaf,我们不知道,问题没有说明。我以为我提到信息丢失了,我还想过我提到了可能的别名问题?我很乐意看到这方面的验证。 – ilkkachu

+0

upub/carr是**,如标题所示** uchar' /'uint8_t'数组。 '*(uint64_t *)(upub + 33)= __builtin_bswap64(PplusQ [di] [3]);'适用于所有警告,迂腐和其他哨声启用。它也比原始代码更快。 – Perlator

1

可以复制为:

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

假设upub是指针变量

+0

工程,但比原始代码慢。 – Perlator

1

当写入端无关的代码不存在的替代比特移位。你的代码可能已经接近理想。

你可以玩的是使用循环而不是硬编码的数字。沿此线的东西:

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

这可能会变成慢或快于或等于相比,你已经拥有,取决于系统。总体而言,在没有考虑特定系统的情况下讨论像这样的手动优化没有任何意义。