C:Memcpy vs Shifting:哪个更有效率?

标签 c performance casting benchmarking memcpy

我有一个包含 16 位和 32 位数据样本的字节数组,为了将它们转换为 Int16 和 Int32,我目前只使用 2(或 4)个字节执行 memcpy。

因为 memcpy 可能没有针对只有两个字节的长度进行优化,我想知道使用整数运算(或 union )将字节转换为 Int32 是否会更有效。

我想知道调用 memcpy 与位移位的效率是多少,因为代码在嵌入式平台上运行。

最佳答案

我会说 memcpy 不是执行此操作的方法。但是,找到最佳方法在很大程度上取决于数据在内存中的存储方式。

首先,您不想获取目标变量的地址。如果它是局部变量,您将强制将其压入堆栈,而不是让编译器选择将其放入处理器寄存器。仅此一项就可能非常昂贵。

最通用的解决方案是逐字节读取数据并将结果进行算术组合。例如:

uint16_t res = (  (((uint16_t)char_array[high]) << 8)
                | char_array[low]);

32 位情况下的表达式有点复杂,因为您有更多选择。您可能想要检查最佳的汇编器输出。

Alt 1: build 巴黎,并将它们组合起来:

uint16_t low16 = ... as example above ...;
uint16_t high16 = ... as example above ...;
uint32_t res = (  (((uint32_t)high16) << 16)
                | low16);

备选方案 2:一次移入 8 位:

uint32_t res = char_array[i0];
res = (res << 8) | char_array[i1];
res = (res << 8) | char_array[i2];
res = (res << 8) | char_array[i3];

上面的所有示例对于所用处理器的字节序都是中性的,因为索引值决定要读取的部分。

如果 1) 设备的字节顺序(字节顺序)与字节存储在数组中的顺序相匹配,并且 2) 已知数组放置在对齐的内存地址上,则可以采用下一种解决方案。后一种情况取决于机器,但如果代表 16 位数组的 char 数组从偶数地址开始,那么你是安全的,而在 32 位情况下,它应该从可被 4 整除的地址开始。在这种情况下,您可以在一些指针技巧之后简单地读取地址:

uint16_t res = *(uint16_t *)&char_array[xxx];

其中xxx是内存中第一个字节对应的数组索引。请注意,这可能与最低值的索引不同。

我强烈建议使用第一类解决方案,因为它是字节序中立的。

无论如何,它们都比您的memcpy 解决方案快得多。

关于C:Memcpy vs Shifting:哪个更有效率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9160823/

相关文章:

c++ - 将 int 转换为 void 指针

c - 链表没有创建,为什么? [CS50 pset4]

php - 在 MySQL 中构建面包屑

javascript - Youtube 嵌入延迟解析

未知长度的 C 字符串定义

java - ClassCastException 使用 Class.cast 使用泛型

c - 为什么这个断言会失败呢?

检查我对特定角色的内存 - 做不到

c - 字符串创建问题 C

mysql - LEFT JOIN 优化