将字节反转 uint64_t 复制到 uint8_t 数组
copy byte-reversed uint64_t to uint8_t array
我知道如何反转字节顺序 (convert big endian to little endian in C [without using provided func]) - 在这种情况下我想使用 __builtin_bswap64
我也知道如何将 64 位 uint 复制到 char 数组 - 最好是 memcopy。 (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);
由于 memcopy 没有将 __builtin_bswap64 的结果作为源参数(或者是吗?),我尝试了这个:
*(uint64_t *)upub+33 = __builtin_bswap64(some64bitvalue);
但我最终得到了
错误:需要左值作为赋值的左操作数
是否有比我尝试替换的原始代码更快的替代方案?
这个:
*(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]);
或者您的意思是先将 upub
转换为 uint64_t *
,正如阿空加瓜评论的那样?
*((uint64_t *) upub + 33) = __builtin_bswap64(PplusQ[di][3]);
我没看到upub
的类型,所以无法判断。
此外,我感觉如果 upub
最初指向另一种类型,aliasing rules 可能存在问题,因此您可能需要使用类似 gcc 的 -fno-strict-aliasing
或通过联合进行赋值,或者像您的第一个代码片段中那样一次一个字节。
您可以复制为:
uint64_t tmp = __builtin_bswap64(some64bitvalue);
memcpy(upub+33,&tmp,sizeof(tmp));
假设upub是指针变量
在编写与字节序无关的代码时,除了移位之外别无选择。您的代码可能已经接近理想。
您可以尝试使用循环而不是硬编码数字。类似这样的事情:
for(uint_fast8_t i=0; i<8; i++)
{
carr[i+offset] = (some64bitvalue >> (56-(i*8)) & 0xFF;
}
与您现有的相比,这可能会变慢或变快或相等,具体取决于系统。总的来说,如果不考虑特定的系统,讨论这样的手动优化是没有任何意义的。
我知道如何反转字节顺序 (convert big endian to little endian in C [without using provided func]) - 在这种情况下我想使用 __builtin_bswap64
我也知道如何将 64 位 uint 复制到 char 数组 - 最好是 memcopy。 (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);
由于 memcopy 没有将 __builtin_bswap64 的结果作为源参数(或者是吗?),我尝试了这个:
*(uint64_t *)upub+33 = __builtin_bswap64(some64bitvalue);
但我最终得到了 错误:需要左值作为赋值的左操作数
是否有比我尝试替换的原始代码更快的替代方案?
这个:
*(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]);
或者您的意思是先将 upub
转换为 uint64_t *
,正如阿空加瓜评论的那样?
*((uint64_t *) upub + 33) = __builtin_bswap64(PplusQ[di][3]);
我没看到upub
的类型,所以无法判断。
此外,我感觉如果 upub
最初指向另一种类型,aliasing rules 可能存在问题,因此您可能需要使用类似 gcc 的 -fno-strict-aliasing
或通过联合进行赋值,或者像您的第一个代码片段中那样一次一个字节。
您可以复制为:
uint64_t tmp = __builtin_bswap64(some64bitvalue);
memcpy(upub+33,&tmp,sizeof(tmp));
假设upub是指针变量
在编写与字节序无关的代码时,除了移位之外别无选择。您的代码可能已经接近理想。
您可以尝试使用循环而不是硬编码数字。类似这样的事情:
for(uint_fast8_t i=0; i<8; i++)
{
carr[i+offset] = (some64bitvalue >> (56-(i*8)) & 0xFF;
}
与您现有的相比,这可能会变慢或变快或相等,具体取决于系统。总的来说,如果不考虑特定的系统,讨论这样的手动优化是没有任何意义的。